java中的token认证

上篇博文写了限制ip访问次数,这次写token认证。token认证必须是在用户登录之后,用jwt生成,然后将token信息存到response的消息头中来实现的。首先要放行登录的controller,未登录之前不需要token认证,登录之后再进行token认证。验证过程为:首先获取头信息,取出头信息中的内容。调用工具类获取出用户名,根据已登录的用户名集合判断是否是登录状态,登录的用户名集合是存放在redis中的。最后再判断token的过期时间。工具类我会在最下方贴出来

登录

@Autowired
    private JwtTool jwtTool;  // 工具类
    @Autowired
    private LoginService loginService   // 登陆方法service层
    @Autowired
    private RedisTemplate redisTemplate;  // redis
    @Value("${jwt.header}")
    private String header;   // 读取配置文件
    @Value("${jwt.tokenHead}")
    private String tokenHead;
 @RequestMapping("/login")
    public ResponseBody login(UserPo userPo, HttpServletResponse response) {
        ResponseBody responseBody = new ResponseBody();
        String username = userPo.getUsername();
        String password = userPo.getPassword();
        if (StringUtils.isBlank(username)) {  // 用户名为空
            return DyTool.responseReturn(StatusEnum.USERNAMEISNULL);   // (工具类)
        }
        if (StringUtils.isBlank(password)) {  // 密码为空
            return DyTool.responseReturn(StatusEnum.PASSWORDISNULL);  // (工具类)
        }
        userPo = loginService.findUserByName(username);
        if (!userPo.getPassword().equals(SecuritySHATool.md5Encrypt(password))) { // // (工具类)密码错误(MD5加密)
            return DyTool.responseReturn(StatusEnum.PASSWORDERROR);  //(工具类)
        }
        response.setHeader(header, tokenHead + jwtTool.generateToken(username));  // (工具类)
        BoundSetOperations userSet = redisTemplate.boundSetOps("usernameSet");
        userSet.add(username);
        return DyTool.responseReturn(StatusEnum.LOGINSUCCESS); //(工具类)登录成功
    }

验证token

 @Autowired
    private JwtTool jwtTool;  // 工具类
    @Value("${jwt.header}")
    private String tokenHeader; // 读取的配置文件(自己写就可以)
    @Value("${jwt.tokenHead}")
    private String tokenHead
    // 获取header中的token信息
    String authHeader = httpServletRequest.getHeader(this.tokenHeader);
    if (authHeader == null || !authHeader.startsWith(this.tokenHead)) {  // 是否含有token的头信息
        DyTool.responseWriter(StatusEnum.NOHEADER, httpServletResponse);  //(工具类) 缺少头信息
        return;
    }
    final String authToken = authHeader.substring(tokenHead.length()); // "Bearer "
    String useraccount = jwtTool.getUserAccountFromToken(authToken);  // (工具类)获取出token中的用户名
    BoundSetOperations usernameSet = redisTemplate.boundSetOps("usernameSet");  // 取出redis中的在线用户名集合
    logger.info("token验证过滤器[JwtAuthenticationTokenFilter]_用户名为:" + useraccount);
    if (!usernameSet.isMember(useraccount)) { // 是否登录过
        DyTool.responseWriter(StatusEnum.UNLOGIN, httpServletResponse);  //(工具类) 未登录
        return;
    }
    username = useraccount;
    if (jwtTool.isTokenExpired(authToken)) {  // (工具类)验证过期时间
        DyTool.responseWriter(StatusEnum.TOKENOUTTIME, httpServletResponse);  // (工具类)验证token失败
        return;
    }

工具类

/**
 * @Description: JWT工具类,里面的方法未写成静态方法,需要注入
 * @Author: 臧东运
 * @CreateTime: 2019/4/17 13:58
 */
@Component
public class JwtTool {
    private static final String CLAIM_KEY_USER_ACCOUNT = "sub";
    private static final String CLAIM_KEY_CREATED = "created";

    @Value("${jwt.secret}")
    private String secret; //秘钥   // 读取配置文件,自己配置

    @Value("${jwt.expiration}")
    private Long expiration; //过期时间

    /**
     * 从token中获取用户account
     * @param token
     * @return
     */
    public String getUserAccountFromToken(String token) {
        String useraccount;
        try {
            final Claims claims = getClaimsFromToken(token);
            useraccount = claims.getSubject();
        } catch (Exception e) {
            useraccount = null;
        }
        return useraccount;
    }

    /**
     * 从token中获取创建时间
     * @param token
     * @return
     */
    public Date getCreatedDateFromToken(String token) {
        Date created;
        try {
            final Claims claims = getClaimsFromToken(token);
            created = new Date((Long) claims.get(CLAIM_KEY_CREATED));
        } catch (Exception e) {
            created = null;
        }
        return created;
    }

    /**
     * 获取token的过期时间
     * @param token
     * @return
     */
    public Date getExpirationDateFromToken(String token) {
        Date expiration;
        try {
            final Claims claims = getClaimsFromToken(token);
            expiration = claims.getExpiration();
        } catch (Exception e) {
            expiration = null;
        }
        return expiration;
    }

    /**
     * 从token中获取claims
     * @param token
     * @return
     */
    private Claims getClaimsFromToken(String token) {
        Claims claims;
        try {
            claims = Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception e) {
            claims = null;
        }
        return claims;
    }

    /**
     * 生存token的过期时间
     * @return
     */
    private Date generateExpirationDate() {
        return new Date(System.currentTimeMillis() + expiration * 1000);
    }
    
    /**
     * 判断token是否过期
     * @param token
     * @return
     */
    public Boolean isTokenExpired(String token) {
        final Date expiration = getExpirationDateFromToken(token);
        Boolean result= expiration.before(new Date());
        return result;
    }
    
    /**
     * 生成token
     * @param usernmae
     * @return
     */
    public String generateToken(String usernmae) {
        Map<String, Object> claims = new HashMap<>();
        claims.put(CLAIM_KEY_USER_ACCOUNT, usernmae);
        claims.put(CLAIM_KEY_CREATED, new Date());
        return generateToken(claims);
    }

    String generateToken(Map<String, Object> claims) {
        return Jwts.builder()
                .setClaims(claims)
                .setExpiration(generateExpirationDate())
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();
    }

    /**
     * token 是否可刷新
     * @param token
     * @return
     */
    public Boolean canTokenBeRefreshed(String token) {
        final Date created = getCreatedDateFromToken(token);
        return !isTokenExpired(token);
    }

    /**
     * 刷新token
     * @param token
     * @return
     */
    public String refreshToken(String token) {
        String refreshedToken;
        try {
            final Claims claims = getClaimsFromToken(token);
            claims.put(CLAIM_KEY_CREATED, new Date());
            refreshedToken = generateToken(claims);
        } catch (Exception e) {
            refreshedToken = null;
        }
        return refreshedToken;
    }

    /**
     * 验证token
     * @param token
     * @param usernmae
     * @return
     */
    public Boolean validateToken(String token, String usernmae) {
        final String useraccount = getUserAccountFromToken(token);
        final Date created = getCreatedDateFromToken(token);
        Boolean result= (
                useraccount.equals(usernmae)
                        && !isTokenExpired(token)
        );
        return result;
    }
}
 /** 
     * @param statusEnum  状态枚举类
     * @param response
     * @return java.lang.String
     * @Description: 发生错误时响应给请求者, 拦截器过滤器层面,需要HttpServletResponse
     * @Author Zangdy
     * @CreateTime 2019/4/22 11:09
     */
    public static void responseWriter(StatusEnum statusEnum, HttpServletResponse response) throws IOException {
        ResponseBody responseBody = new ResponseBody();
        responseBody.setStatus(statusEnum.getStatus());
        responseBody.setMessage(statusEnum.getMessage());
        response.setContentType("text/html; charset=UTF-8");
        response.getWriter().write(JSONObject.toJSONString(responseBody));
    }
    /**
     * @param statusEnum
     * @return java.lang.String
     * @Description: 发生错误时响应给请求者, Controller层面,不需要HttpServletResponse
     * @Author Zangdy
     * @CreateTime 2019/4/22 11:09
     */
    public static ResponseBody responseReturn(StatusEnum statusEnum){
        ResponseBody responseBody = new ResponseBody();
        responseBody.setStatus(statusEnum.getStatus());
        responseBody.setMessage(statusEnum.getMessage());
        return responseBody;
    }
/**
 * @Description:  状态枚举类
 * @Author: 臧东运
 * @CreateTime: 2019/4/22 10:53
 */
public enum  StatusEnum {

    UNLOGIN("0000","未登录"),

    /**
     * 状态 02 开头为成功
     * */
    LOGINSUCCESS("0201","登陆成功"),
    LOGOUTSUCCESS("0202","注销成功"),
    UPLOADSUCCESS("0203","文件上传成功"),


    /**
     * 状态 04 开头为失败
     */
    IPBLOCKED("0400","因非法请求,已被禁止访问,请稍后重试!"),
    ACCESSDENIED("0401","无权限访问"),
    USERNAMEISNULL("0402","用户名不能为空!"),
    PASSWORDISNULL("0402","密码不能为空!"),
    USERNAMEERROR("0402","用户名错误!"),
    PASSWORDERROR("0402","密码错误!"),
    NOHEADER("0403","缺少头信息"),
    TOKENOUTTIME("0404","token认证已过期"),
    APPTIMESIGNISNULL("0405","sign认证参数为空"),
    SIGNUNTRUE("0406","sign参数不正确"),
    SIGNOUTTIME("0407","sign签名已过期"),

    ERROR("0499","服务器异常,请稍后重试。如有问题,请联系管理员"),
    CUSTOM("0500","自定义异常");

    private String status;
    private String message;

    StatusEnum(String status, String message) {
        this.status = status;
        this.message = message;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值