栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot前后端分离项目使用SpringSecurity+JWT做权限认证,修改自定义认证过滤器的访问路径

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot前后端分离项目使用SpringSecurity+JWT做权限认证,修改自定义认证过滤器的访问路径

写在前面:

这个问题在网上一直找不到我想要的答案,是通过我自己不断试错最后才成功的,故写出来分享一下。这是我的第一篇分享博客,如果有哪里写的不好的地方,请多多见谅!

需求提出:

SpringSecurity自带的权限认证有很多种,有Form Login的形式,也有http basic的形式等等。我们之前的JSP项目是通过

标签表单提交来进行登录认证的,这时候使用SpringSecurity的Form Login认证是最适合的,并且我们也可以在配置类中可以使用HttpSecurity对象做一些自定义的配置(登录处理器,username参数名,password参数名等等),如下代码所示:

http.formLogin()
            .loginProcessingUrl("/user/login")
            .usernameParameter("account")
            .passwordParameter("password")
            .permitAll();

通过几行简简单单的配置我们就可以将用户认证处理器url修改成/user/login了。

但是在前后端分离的项目中,如果我们要实现登录认证,就要使用Token来保存用户信息,并且要自定义一个用于登录认证的过滤器,继承UsernamePasswordAuthenticationFilter这个类,重写SpringSecurity的认证逻辑。我用到的是JWT来生成Token,这里贴出我的认证代码:

@Slf4j
public class JwtLoginFilter extends UsernamePasswordAuthenticationFilter {

    private final RsaKeys rsaKeys;
    private final AuthenticationManager authenticationManager;

    public JwtLoginFilter(AuthenticationManager manager, RsaKeys rsaKeys) {
        this.authenticationManager = manager;
        this.rsaKeys = rsaKeys;
    }

    
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        log.info("调用了自定义的登录认证过滤器");
        // 获取登录参数
        String account = request.getParameter("account");
        String password = request.getParameter("password");
        if(!StringUtils.hasText(account) || !StringUtils.hasText(password)) {
            // 参数不合法
            ResponseUtils.write(response, ResponseVO.fail(SysCode.UN_VALID_REQUEST_PARAMETER));
            return null;
        }
        // 构造SpringSecurity登录token
        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(account, password);
        return this.authenticationManager.authenticate(token);
    }

    
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        // 获取认证用户对象,去除敏感信息
        User user = (User) authResult.getPrincipal();
        user.setPassword(null);
        // 生成Token
        String authorization = JwtUtils.generateToken(user, rsaKeys.getPrivateKey());
        // 存入响应头并返回
        response.setHeader("Authorization", "Bearer " + authorization);
        ResponseUtils.write(response, ResponseVO.ok(SysCode.LOGIN_SUCCESS));
    }

    
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        ResponseUtils.write(response, ResponseVO.fail(SysCode.BAD_AUTHENTICATE));
    }
}

 这样子配置之后,再在SpringSecurity配置类中使用http.addFilter加入我们自定义的这个过滤器就可以通过请求http://localhost:8080/login接口并且携带登录参数来进行登录认证了,认证成功之后会将Token设置在响应头中,然后前端拿到Token进行其他的请求。

 那么,如果我不想要这个默认接口呢?我的接口规范就是要/api @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { log.info("调用了自定义的登录认证过滤器"); // 获取登录参数 String account = request.getParameter("account"); String password = request.getParameter("password"); if(!StringUtils.hasText(account) || !StringUtils.hasText(password)) { // 参数不合法 ResponseUtils.write(response, ResponseVO.fail(SysCode.UN_VALID_REQUEST_PARAMETER)); return null; } // 构造SpringSecurity登录token UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(account, password); return this.authenticationManager.authenticate(token); } @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { // 获取认证用户对象,去除敏感信息 User user = (User) authResult.getPrincipal(); user.setPassword(null); // 生成Token String authorization = JwtUtils.generateToken(user, rsaKeys.getPrivateKey()); // 存入响应头并返回 response.setHeader("Authorization", "Bearer " + authorization); ResponseUtils.write(response, ResponseVO.ok(SysCode.LOGIN_SUCCESS)); } @Override protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException { ResponseUtils.write(response, ResponseVO.fail(SysCode.BAD_AUTHENTICATE)); } }

在SpringSecurity配置类中,无需添加http.formLogin配置,只要配置自定义过滤器即可

@Override
protected void configure(HttpSecurity http) throws Exception {
    // 放行所有接口,由注解进行限制
    http.authorizeRequests()
            .antMatchers("/**").permitAll();
    // 添加自定义的过滤器
    http.addFilter(new JwtLoginFilter(authenticationManager(), rsaKeys))
            .addFilter(new JwtVerifyTokenFilter(authenticationManager(), rsaKeys));
    // csrf拦截
    http.csrf().disable();
}

 

 以上就是本篇文章的所有内容了,希望对你有帮助!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/775955.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号