zoukankan      html  css  js  c++  java
  • SpringBoot 使用jwt进行身份验证

    这里只供参考,比较使用jwt方式进行身份验证感觉不好,最不行的就是不能退出

    登陆时设定多长过期时间,只能等这个时间过了以后才算退出,服务端只能验证请求过来的token是否通过验证

    Code:

    /**
     * Created by qhong on 2018/6/7 15:34
     * 标注该注解的,就不需要登录
     **/
    @Target({ElementType.METHOD,ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface AuthIgnore {
    
    }

    LoginUser:

    @Target(ElementType.PARAMETER)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface LoginUser {
    
    }

    JwtUtil:

    @ConfigurationProperties(prefix = "jwt")
    @Component
    public class JwtUtils {
        private Logger logger = LoggerFactory.getLogger(getClass());
    
        private String secret;
        private long expire;
        private String header;
    
        /**
         * 生成jwt token
         */
        public String generateToken(long userId) {
            Date nowDate = new Date();
            //过期时间
            Date expireDate = new Date(nowDate.getTime() + expire * 1000);
    
            return Jwts.builder()
                    .setHeaderParam("typ", "JWT")
                    .setSubject(userId+"")
                    .setIssuedAt(nowDate)
                    .setExpiration(expireDate)
                    .signWith(io.jsonwebtoken.SignatureAlgorithm.HS512, secret)
                    .compact();
        }
    
        public Claims getClaimByToken(String token) {
            try {
                return Jwts.parser()
                        .setSigningKey(secret)
                        .parseClaimsJws(token)
                        .getBody();
            }catch (Exception e){
                logger.debug("validate is token error ", e);
                return null;
            }
        }
    
        /**
         * token是否过期
         * @return  true:过期
         */
        public boolean isTokenExpired(Date expiration) {
            return expiration.before(new Date());
        }
    
        public String getSecret() {
            return secret;
        }
    
        public void setSecret(String secret) {
            this.secret = secret;
        }
    
        public long getExpire() {
            return expire;
        }
    
        public void setExpire(long expire) {
            this.expire = expire;
        }
    
        public String getHeader() {
            return header;
        }
    
        public void setHeader(String header) {
            this.header = header;
        }
    }

    application.properties配置:

    # 加密秘钥
    jwt.secret=f4e2e52034348f86b67cde581c0f9eb5
    # token有效时长,单位秒
    jwt.expire=60000
    jwt.header=token

    拦截器:

    /**
     * Created by qhong on 2018/6/7 15:36
     **/
    @Component
    public class AuthorizationInterceptor extends HandlerInterceptorAdapter {
        @Autowired
        private JwtUtils jwtUtils;
    
        public static final String USER_KEY = "userId";
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            AuthIgnore annotation;
            if(handler instanceof HandlerMethod) {
                annotation = ((HandlerMethod) handler).getMethodAnnotation(AuthIgnore.class);
            }else{
                return true;
            }
    
            //如果有@AuthIgnore注解,则不验证token
            if(annotation != null){
                return true;
            }
    
            //获取用户凭证
            String token = request.getHeader(jwtUtils.getHeader());
            if(StringUtils.isBlank(token)){
                token = request.getParameter(jwtUtils.getHeader());
            }
    
            //token凭证为空
            if(StringUtils.isBlank(token)){
                throw new AuthException(jwtUtils.getHeader() + "不能为空", HttpStatus.UNAUTHORIZED.value());
            }
    
            Claims claims = jwtUtils.getClaimByToken(token);
            if(claims == null || jwtUtils.isTokenExpired(claims.getExpiration())){
                throw new AuthException(jwtUtils.getHeader() + "失效,请重新登录", HttpStatus.UNAUTHORIZED.value());
            }
    
            //设置userId到request里,后续根据userId,获取用户信息
            request.setAttribute(USER_KEY, Long.parseLong(claims.getSubject()));
    
            return true;
        }
    }

    注解拦截:

    @Component
    public class LoginUserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
        @Autowired
        private UserService userService;
    
        @Override
        public boolean supportsParameter(MethodParameter parameter) {
            return parameter.getParameterType().isAssignableFrom(User.class) && parameter.hasParameterAnnotation(LoginUser.class);
        }
    
        @Override
        public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer container,
                                      NativeWebRequest request, WebDataBinderFactory factory) throws Exception {
            //获取用户ID
            Object object = request.getAttribute(AuthorizationInterceptor.USER_KEY, RequestAttributes.SCOPE_REQUEST);
            if(object == null){
                return null;
            }
    
            //获取用户信息
            User user = userService.selectById((Long)object);
    
            return user;
        }
    }

    WebConfig:

    @Configuration
    public class WebConfig extends WebMvcConfigurerAdapter {
    
        @Autowired
        private AuthorizationInterceptor authorizationInterceptor;
        @Autowired
        private LoginUserHandlerMethodArgumentResolver loginUserHandlerMethodArgumentResolver;
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(authorizationInterceptor).addPathPatterns("/**");
        }
    
        @Override
        public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
            argumentResolvers.add(loginUserHandlerMethodArgumentResolver);
        }
    
    }

    Login:

        @PostMapping("/login")
        @AuthIgnore
        public R login2(@RequestBody User u){
    
            //用户登录
            long userId =userService.addUser(u);
    
            //生成token
            String token = jwtUtils.generateToken(userId);
    
            Map<String, Object> map = new HashMap<>();
            map.put("token", token);
            map.put("expire", jwtUtils.getExpire());
    
            return R.ok(map);
        }

    LoginUser注解使用:

    @RequestMapping(value="/query2",method= RequestMethod.POST)
        public User Query2(@LoginUser User u){
             return u;
        }

    https://www.cnblogs.com/xiekeli/p/5607107.html

    https://gitee.com/renrenio/renren-fast

  • 相关阅读:
    初识MySQL
    正则表达式
    多线程
    多进程
    Python基础--模块
    Python基础--异常
    Python基础--面向对象
    Python基础--文件操作
    Python基础--函数
    python3 日期时间差计算
  • 原文地址:https://www.cnblogs.com/hongdada/p/9152291.html
Copyright © 2011-2022 走看看