SpringBoot集成JWT

作者: 皮多堡 | 来源:发表于2018-06-20 14:38 被阅读53次

    JWT是一种用于双方之间传递安全信息的简洁的、URL安全的表述性声明规范。JWT作为一个开放的标准(RFC 7519),定义了一种简洁的,自包含的方法用于通信双方之间以Json对象的形式安全的传递信息。因为数字签名的存在,这些信息是可信的,JWT可以使用HMAC算法或者是RSA的公私秘钥对进行签名。简洁(Compact): 可以通过URL,POST参数或者在HTTP header发送,因为数据量小,传输速度也很快 自包含(Self-contained):负载中包含了所有用户所需要的信息,避免了多次查询数据库

    • 1.账户实体类
    @Data
    public class Account {
        public String username;
        public String password;
    }
    
    • 2.认证过滤器
    public class JwtAuthenticationFilter extends OncePerRequestFilter {
    
        private static final PathMatcher PATH_MATCHER = new AntPathMatcher();
    
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    
            try {
                if(isProtectedUrl(request)) {
                    request = JwtUtil.  validateTokenAndAddUserIdToHeader(request);
                }
            } catch (Exception e) {
                response.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());
                return;
            }
            filterChain.doFilter(request, response);
        }
    
        private boolean isProtectedUrl(HttpServletRequest request) {
            return PATH_MATCHER.match("/api/**", request.getServletPath());
        }
    
    }
    
    • 3.jwt生成与校验
    public class JwtUtil {
        private static final Logger logger = LoggerFactory.getLogger(JwtUtil.class);
        /**
         * 1000 hour
         */
        private static final long EXPIRATION_TIME = 3600_000_000L;
        private static final String SECRET = "ThisIsASecret";
        private static final String TOKEN_PREFIX = "Bearer ";
        private static final String HEADER_STRING = "Authorization";
        public static final String USER_NAME = "userName";
    
        /**
         * 生成token
         */
        public static String generateToken(String userName) {
            HashMap<String, Object> map = Maps.newHashMap();
            map.put(USER_NAME, userName);
            String jwt = Jwts.builder()
                    .setClaims(map)
                    .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
                    .signWith(SignatureAlgorithm.HS512, SECRET)
                    .compact();
            //jwt前面一般都会加Bearer
            return TOKEN_PREFIX + jwt;
        }
    
        /**
         * 校验、解析token
         */
        public static HttpServletRequest validateTokenAndAddUserIdToHeader(HttpServletRequest request) {
            String token = request.getHeader(HEADER_STRING);
            if (token != null) {
                try {
                    Map<String, Object> body = Jwts.parser()
                            .setSigningKey(SECRET)
                            .parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
                            .getBody();
                    return new CustomHttpServletRequest(request, body);
                } catch (Exception e) {
                    logger.info(e.getMessage());
                    throw new TokenValidationException(e.getMessage());
                }
            } else {
                throw new TokenValidationException("Missing token");
            }
        }
    
        public static class CustomHttpServletRequest extends HttpServletRequestWrapper {
            private Map<String, String> claims;
    
            public CustomHttpServletRequest(HttpServletRequest request, Map<String, ?> claims) {
                super(request);
                this.claims = new HashMap<>();
                claims.forEach((k, v) -> this.claims.put(k, String.valueOf(v)));
            }
    
            @Override
            public Enumeration<String> getHeaders(String name) {
                if (claims != null && claims.containsKey(name)) {
                    return Collections.enumeration(Arrays.asList(claims.get(name)));
                }
                return super.getHeaders(name);
            }
    
            public Map<String, String> getClaims() {
                return claims;
            }
        }
    
        static class TokenValidationException extends RuntimeException {
            public TokenValidationException(String msg) {
                super(msg);
            }
        }
    }
    
    • 4.测试controller
    @RestController
    @Slf4j
    public class JwtController {
    
        //需要token的接口
        @GetMapping("/api/protected")
        public Object hellWorld(@RequestHeader(value = USER_NAME) String userName) {
            log.info("user -- {}", userName);
            return "Success - AccessToken is validated ...";
        }
    
        @GetMapping("/hello")
        public String hello() {
            return "hello world";
        }
    
    
        //登录 成功后返回token
        @PostMapping("/login")
        public Object login(@RequestBody final Account account){
    
            if (!isValidPassword(account)) {
                return new ResponseEntity(HttpStatus.UNAUTHORIZED);
            }
    
            String jwt = JwtUtil.generateToken(account.username);
            return new HashMap<String,String>(){{
                put("token", jwt);
            }};
        }
    
    
    
        private boolean isValidPassword(Account credentials) {
            if ("admin".equals(credentials.username)
                    && "admin".equals(credentials.password)) {
                return true;
            }
            return false;
        }
    
    }
    
    • 5.启动类
    @SpringBootApplication
    @Slf4j
    public class JwtApplication {
    
        public static void main(String[] args) {
            SpringApplication app = new SpringApplication(JwtApplication.class);
            app.setBannerMode(Banner.Mode.CONSOLE);
            app.run(args);
            log.info("PortalApplication is success!");
        }
    
        //注册过滤器
        @Bean
        public FilterRegistrationBean jwtFilter() {
            final FilterRegistrationBean registrationBean = new FilterRegistrationBean();
            registrationBean.setFilter(new JwtAuthenticationFilter());
            return registrationBean;
        }
    
    }
    
    • 6.测试


    生成token如下

    {
        "token": "Bearer eyJhbGciOiJIUzUxMiJ9.eyJ1c2VyTmFtZSI6ImFkbWluIiwiZXhwIjoxNTMzMDY0NzExfQ.8TGWbR8RXJS743u6hINmxnqLwycPZTN3iNPtKyW74rEBnLS3V0r0we9vJThfTVoz7bHYUa_R-nGiOiBGtq8XDA"
    }
    

    请求头里带上token正常访问:


    相关文章

      网友评论

        本文标题:SpringBoot集成JWT

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