Spring security--jwt身份验证

项目背景:项目由springboot构建,通过jwt进行认证和授权,这是无连接、无状态的。要实现用户唯一性,无法通过session等其他入手。

前期分析:

认证这里是通过fliter获取请求中的token

public class JWTFilter extends GenericFilterBean {

    public static final String AUTHORIZATION_HEADER = "Authorization";

    private TokenProvider tokenProvider;

    public JWTFilter(TokenProvider tokenProvider) {
        this.tokenProvider = tokenProvider;
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
        throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        String jwt = resolveToken(httpServletRequest);
        if (StringUtils.hasText(jwt) && this.tokenProvider.validateToken(jwt)) {
            Authentication authentication = this.tokenProvider.getAuthentication(jwt);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
        filterChain.doFilter(servletRequest, servletResponse);
    }

    private String resolveToken(HttpServletRequest request){
        String bearerToken = request.getHeader(AUTHORIZATION_HEADER);
        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }
}

随后tokenProvider.validateToken(jwt)这里对token解析,也只是通过简单的验证,看通过密钥能不能正常解析出,解析不出或者异常即验证不通过

public boolean validateToken(String authToken) {
    try {
        Jwts.parser().setSigningKey(key).parseClaimsJws(authToken);
        return true;
    } catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) {
        log.info("Invalid JWT signature.");
        log.trace("Invalid JWT signature trace: {}", e);
    } catch (ExpiredJwtException e) {
        log.info("Expired JWT token.");
        log.trace("Expired JWT token trace: {}", e);
    } catch (UnsupportedJwtException e) {
        log.info("Unsupported JWT token.");
        log.trace("Unsupported JWT token trace: {}", e);
    } catch (IllegalArgumentException e) {
        log.info("JWT token compact of handler are invalid.");
        log.trace("JWT token compact of handler are invalid trace: {}", e);
    }
    return false;
}

这里要实现用户唯一,要做到两点:

1、对用户登录后的token需要持久化(redis或者直接入库)。

2、在验证时,我你们需要解析token,获取用户信息,并于存储的token比对,一致则通过,否则限制访问。

实现:

这里预期实现,A用户在地点1登录,并不退出。随后A用户在地点2登录。如果地点1再有任何操作,回限制访问,并返回登陆页面。

首先改写dofliter,在这里,我们需要获取到token,并去除掉登录的接口,不然发现这个用户已经登陆过,在地点2的登陆请求会被拦截。

a01423a6da780d6ecd49713dfe0fca4b3d9.jpg

随后根据解析出的用户信息,从存储中获取登录时记录的token进行校验。这里获取用户信息,我也是和上面解析token的校验一样,通过密钥解析token。

private boolean isOtherLogin(String jwt){
    boolean result = false;
    //判断当前用户是否 已在异地登陆
    String username = this.tokenProvider.getUserName(jwt);
    if(username!=null&&!"".equals(username)){
        log.info("username of isOtherLogin:{}",username);
        List<PersistentToken> persistentTokenList = persistentTokenService.findByUserAgentOrderByTokenDateDesc(username);
        if(persistentTokenList!=null&&persistentTokenList.size()>0){
            String user_token = persistentTokenList.get(0).getTokenValue();
            if(!jwt.equals(user_token)){
                result = true;
            }
        }
    }
    log.info("result of isOtherLogin:{}",result);
    return result;
}

转载于:https://my.oschina.net/zyldsy/blog/3077258

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值