JWT登陆认证+redis实现自动续期

登陆controller:

复制代码
package login;

import batch.User;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class LoginController {
    @Autowired
    User userMapper;
    @Autowired
    RedisServiceImpl redisService;
    @RequestMapping("/login")
    public String login(String username,String password){
        //1.判断用户名密码是否正确
        JSONObject userPO = userMapper.selectUserByName(username);
        if (userPO == null) {
            throw new RuntimeException("用户名不存在");
        }
        if (!password.equals(userPO.get("password"))) {
            throw new RuntimeException("密码错误");
        }

        //2.用户名密码正确生成token
        UserTokenDTO userTokenDTO = new UserTokenDTO();

        userTokenDTO.setId((int)userPO.get("id"));
        userTokenDTO.setCreateTime( System.currentTimeMillis());
        String token = JWTUtil.generateToken(userTokenDTO);

        //3.存入token至redis
        redisService.set(userPO.get("id").toString(), token);
        return token;
    }
@RequestMapping("/loginOut")
    public boolean loginOut(String id) {
        boolean result = redisService.delete(id);
        if (!redisService.delete(id)) {
            throw new RuntimeException("退出登陆出错");
        }

        return result;
    }
@RequestMapping("/updatePassword")
    public String updatePassword(String id,String password) {
        //1.修改密码
        JSONObject user = userMapper.selectUserById(id);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        if (userMapper.updatePassword(id,password) != 1) {
            throw new RuntimeException("密码更新失败");
        }
        //2.生成新的token
        UserTokenDTO userTokenDTO = new UserTokenDTO();
        userTokenDTO.setId(Integer.parseInt(id));
        userTokenDTO.setCreateTime(System.currentTimeMillis());
        userTokenDTO.setPhone(user.get("phone").toString());
        String token = JWTUtil.generateToken(userTokenDTO);
        //3.更新token
        redisService.set(user.get("id").toString(), token);
        return token;
    }
}
复制代码

UserTokenDTO:

复制代码
package login;

public class UserTokenDTO {
    private int id;
    private String phone;
    private  long createTime;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public Long getCreateTime() {
        return createTime;
    }

    public void setCreateTime(long createTime) {
        this.createTime = createTime;
    }
}
复制代码

JWTUtil:

复制代码
package login;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.util.HashMap;
import java.util.Map;

public class JWTUtil {
    //私钥
    private static final String TOKEN_SECRET = "123456";
/**
     * 生成token,自定义过期时间 毫秒
     *
     * @param userTokenDTO
     * @return
     */
    public static String generateToken(UserTokenDTO userTokenDTO) {

        try {
            // 私钥和加密算法
            Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
            // 设置头部信息
            Map<String, Object> header = new HashMap<>(2);
            header.put("Type", "Jwt");
            header.put("alg", "HS256");

            return JWT.create()
                    .withHeader(header)
                    .withClaim("token", JSONObject.toJSONString(userTokenDTO))
                    .sign(algorithm);
        } catch (Exception e) {
            System.out.println("generate token occur error");
            return null;
        }
    }

/**
     * 检验token是否正确
     *
     * @param token
     * @return
     */
    public static UserTokenDTO parseToken(String token) {
        Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
        JWTVerifier verifier = JWT.require(algorithm).build();
        DecodedJWT jwt = verifier.verify(token);
        String tokenInfo = jwt.getClaim("token").asString();
        return JSON.parseObject(tokenInfo, UserTokenDTO.class);
    }
}
复制代码

RedisServiceImpl(redis操作的封装类):

复制代码
package login;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

public final class RedisServiceImpl  {
    /**
     * 过期时长
     */
    private final Long DURATION = 1 * 24 * 60 * 60 * 1000L;

    @Resource
    private RedisTemplate redisTemplate;

    private ValueOperations<String, String> valueOperations;

    @PostConstruct
    public void init() {
        RedisSerializer redisSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(redisSerializer);
        redisTemplate.setValueSerializer(redisSerializer);
        redisTemplate.setHashKeySerializer(redisSerializer);
        redisTemplate.setHashValueSerializer(redisSerializer);
        valueOperations = redisTemplate.opsForValue();
    }


    public void set(String key, String value) {
        valueOperations.set(key, value, DURATION, TimeUnit.MILLISECONDS);
        log.info("key={}, value is: {} into redis cache", key, value);
    }


    public String get(String key) {
        String redisValue = valueOperations.get(key);
        log.info("get from redis, value is: {}", redisValue);
        return redisValue;
    }


    public boolean delete(String key) {
        boolean result = redisTemplate.delete(key);
        log.info("delete from redis, key is: {}", key);
        return result;
    }


    public Long getExpireTime(String key) {
        return valueOperations.getOperations().getExpire(key);
    }
}
复制代码

TokenIntercept(拦截器,验证token是否需要续期):

复制代码
package login;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class TokenIntercept implements HandlerInterceptor {
    @Autowired
    RedisServiceImpl redisService;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String authToken = request.getHeader("Authorization");
        String token = authToken.substring("Bearer".length() + 1).trim();
        UserTokenDTO userTokenDTO = JWTUtil.parseToken(token);
        //1.判断请求是否有效
        if (redisService.get(String.valueOf(userTokenDTO.getId())) == null
                || !redisService.get(String.valueOf(userTokenDTO.getId())).equals(token)) {
            return false;
        }

        //2.判断是否需要续期
        if (redisService.getExpireTime(String.valueOf(userTokenDTO.getId())) < 1 * 60 * 30) {
            redisService.set(String.valueOf(userTokenDTO.getId()), token);
            System.out.println("update token info, id is:"+userTokenDTO.getId()+"user info is:"+token);
        }
        return true;
    }
}
复制代码

InterceptorConfig(拦截器配置类,登陆退出不需要走拦截器):

复制代码
package login;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(TokenIntercept())
                .excludePathPatterns("/logout/**")
                .excludePathPatterns("/login/**")
                .addPathPatterns("/**");
    }

    @Bean
    public TokenIntercept TokenIntercept() {
        return new TokenIntercept();
    }
}
复制代码

 

posted @   杨吃羊  阅读(1091)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
历史上的今天:
2022-02-09 inner join与 left join 和 on与where 的区别
点击右上角即可分享
微信分享提示