SpringBoot jwtによる認証

6306 ワード

ここでは参考までに、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 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 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