美文网首页服务端开发实战Spring-BootSpring Boot
Spring Boot用3个class轻松实现JWT (三) 鉴

Spring Boot用3个class轻松实现JWT (三) 鉴

作者: JonTian | 来源:发表于2018-01-23 13:42 被阅读814次

    请先阅读, Spring Boot用3个class轻松实现JWT (一), 保护你的RESTful API
    基于前两部分略做扩展, 和Spring Security集成在了一起.
    实现了@PreAuthorize的功能
    https://github.com/ZhongjunTian/spring-boot-jwt-demo/tree/master/spring-security-jwt

        @GetMapping("/api/admin")
        @PreAuthorize("hasAuthority('ADMIN_USER')")
        public @ResponseBody
        Object helloToAdmin(String userId) {
            return "Hello World! You are ADMIN ";
        }
    

    和Spring Security集成在一起, 首先要配置, 和前面文章的思想一样, 我们要允许所有/login的请求, 只对其他请求验证权限

    Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable().authorizeRequests()
                    .antMatchers("/").permitAll()
                    .antMatchers(HttpMethod.POST, "/login").permitAll()
                    .anyRequest().authenticated()
                    .and()
                    // We filter the api/** requests
                    .addFilterBefore(new JwtAuthenticationFilter(),
                            UsernamePasswordAuthenticationFilter.class);
        }
    }
    
    

    配置好了之后, 只需要将之前在Spring Boot用3个class轻松实现JWT (一)那篇文章中提到的JwtAuthenticationFilter添加一行代码, 将用户的Role信息注入进去, 然后下一个Filter, 也就是UsernamePasswordAuthenticationFilter就可以得到用户的信息. 这里生成的UsernamePasswordAuthenticationToken的前两个入参用户名和密码是null, 因为我们已经鉴定过jwt了, 只需要用这个token鉴权.

    public class JwtAuthenticationFilter extends OncePerRequestFilter {
      //......一些不重要的代码......
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
            try {
                if (isProtectedUrl(request)) {
                    Map<String, Object> claims = JwtUtil.validateTokenAndGetClaims(request);
                    String role = String.valueOf(claims.get(ROLE));
                    //最关键的部分就是这里, 我们直接注入了Role信息
                    SecurityContextHolder.getContext().setAuthentication(
                            new UsernamePasswordAuthenticationToken(
                                    null, null, Arrays.asList(() -> role)));
                }
            } catch (Exception e) {
                response.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());
                return;
            }
            filterChain.doFilter(request, response);
        }
      //......一些不重要的代码......
    }
    

    我们用账号user, 密码user拿到普通权限的jwt之后, 就只能用/api/hello, 而/api/admin则会被spring security拦截报403错


    主要参考了一下两篇文章, 精简了70%代码
    https://github.com/nydiarra/springboot-jwt
    http://www.baeldung.com/spring-security-oauth-jwt

    相关文章

      网友评论

      • 科学Jia:完美
      • 南京前端架构ztao:具体怎么将token的列表保存,和验证呢?能给个当前最流行的方法的demo不?
        JonTian:不太懂你问的什么意思. 服务器端是不需要保存token的, 因为只需要用RSA密钥验证token.
      • 阿靖_480f:如果用户登录中 token过期怎么办 或者 用户token未过期 又去登录一次 那一个用户就存在两个token了 有好的解决办法吗
        JonTian:jwt 没有revoke的功能. 但是可以application内部cache一个revoke的token列表就行. 用数据库存也行

      本文标题:Spring Boot用3个class轻松实现JWT (三) 鉴

      本文链接:https://www.haomeiwen.com/subject/jedsaxtx.html