jwt+token+登录

TokenUtil

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.fasterxml.jackson.core.type.TypeReference;
import org.springframework.stereotype.Component;
import vip.jiupiao.admin.table.tables.pojos.SysUserEntity;
import vip.jiupiao.common.service.common.JsonUtil;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Component
public class TokenUtil {

    /**
     * 根据用户信息生成token
     *
     * @param sysUserEntity
     * @return
     */
    public static String createToken(SysUserEntity sysUserEntity) {
        return JWT.create()
                // 请求头
                .withHeader(new HashMap<>() {
                    {
                        put("typ", "JWT");
                        put("alg", "HS256");
                    }
                })
                // 负载属性
                .withClaim("obj", JsonUtil.writeValue(sysUserEntity))
                // 签发时间
                .withIssuedAt(new Date())
                // 过期时间
                .withExpiresAt(new Date(System.currentTimeMillis() + 30 * TokenKey.MINUTES))
                // 加密算法 密钥
                .sign(Algorithm.HMAC256(TokenKey.TOKEN_KEY));
    }

    /**
     * 校验token
     *
     * @param token
     * @return
     */
    public static Map<String, Claim> verify(String token) {
        DecodedJWT jwt = null;
        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(TokenKey.TOKEN_KEY)).build();
            jwt = verifier.verify(token);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return jwt.getClaims();
    }

    /**
     * 根据token解析用户信息
     *
     * @param token
     * @return
     */
    public static SysUserEntity getSysUserEntity(String token) {
        Map<String, Claim> claimMap = TokenUtil.verify(Objects.requireNonNull(token));
        String obj = claimMap.get("obj").asString();
        return JsonUtil.readValue(obj, new TypeReference<>() {
        });
    }

    public static void main(String[] args) {
        TokenUtil tokenUtil = new TokenUtil();
        SysUserEntity sysUserEntity = new SysUserEntity();
        sysUserEntity.setId(1L);
        sysUserEntity.setUsername("zhangSan");
        String token = tokenUtil.createToken(sysUserEntity);
        // 生成的token
        System.out.println(token);
        // 解析token获取负载
        System.out.println(getSysUserEntity(token));
    }
}

MyHandlerInterceptor

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import vip.jiupiao.common.constants.exception.ErrorCode;
import vip.jiupiao.common.constants.model.ResponseData;
import vip.jiupiao.common.service.common.JsonUtil;
import vip.jiupiao.utils.StringUtil;

import java.io.PrintWriter;

@Component
public class MyHandlerInterceptor implements HandlerInterceptor {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 请求头中获取token
        String token = request.getHeader("token");
        if (StringUtil.isNotEmpty(token)) {
            // token存在
            String redisKey = TokenKey.REDIS_KEY + TokenUtil.getSysUserEntity(token).getUsername();
            if (token.equals(redisTemplate.opsForValue().get(redisKey))) {
                return true;
            } else {
                response.setContentType("application/json;charset=utf-8");
                PrintWriter out = response.getWriter();
                ResponseData<Object> resp = ResponseData.of(ErrorCode.notLoggedIn);
                out.write(JsonUtil.writeValue(resp));
                return false;
            }
        } else {
            // 没有token
            response.setContentType("application/json;charset=utf-8");
            ResponseData<Object> resp = ResponseData.of(ErrorCode.authUnauthorized);
            response.getWriter().write(JsonUtil.writeValue(resp));
            return false;
        }
    }
}

WebConfig

import org.springframework.beans.factory.annotation.Autowired;
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 WebConfig implements WebMvcConfigurer {
    @Autowired
    private MyHandlerInterceptor handlerInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(handlerInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/sysUser/loginSysUser")
        ;
    }
}

TokenKey

public class TokenKey {
    /**
     * redis token 前缀
     */
    public static final String REDIS_KEY = "jp:token:token_";

    /**
     * 分钟
     */
    public static final long MINUTES = 1000 * 60;

    /**
     * token 密钥
     */
    public static final String TOKEN_KEY = "my_secret";
}

SysUserController

@RequestMapping("sysUser")
@RestController
public class SysUserController {
    @Autowired
    SysUserService sysUserService;
    
    @PostMapping("/loginSysUser")
    public ResponseData loginSysUser(@RequestBody SysUserEntity sysUserEntity) {
        return sysUserService.loginSysUser(sysUserEntity);
    }

    @PostMapping("/logoutSysUser")
    public ResponseData logoutSysUser(@RequestBody SysUserEntity sysUserEntity) {
        return ResponseData.exec(sysUserService.logoutSysUser(sysUserEntity));
    }
}

sysUserService

@Service
public class SysUserServiceImpl implements SysUserService{
	@Override
	public ResponseData loginSysUser(SysUserEntity sysUserEntity) {
	    String token = request.getHeader("token");
	    if (StringUtil.isNotEmpty(token)) {
	        // token存在,到redis中查询是否过期
	        if (Boolean.TRUE.equals(redisTemplate.hasKey(TokenKey.REDIS_KEY + sysUserEntity.getUsername()))) {
	            return ResponseData.exec(SysErrorCode.restrictLoginError);
	        }
	    }
	    SysUserEntity entity = sysUserDao.selectSysUserByUsername(sysUserEntity.getUsername());
	    if (Objects.nonNull(entity)) {
	        if (entity.getStatus() != SysStatusType.ENABLE.getCode()) {
	            return ResponseData.exec(SysErrorCode.userDisableError);
	        }
	        // 校验密码
	        boolean equals = entity.getPassword().equals(DigestUtil.sha256Hex(sysUserEntity.getPassword() + entity.getSalt()));
	        if (equals) {
	            entity.setPassword("");
	            entity.setSalt("");
	            String aToken = TokenUtil.createToken(entity);
	            response.setHeader("token", aToken);
	            // 添加token到redis中
	            CompletableFuture.runAsync(() -> redisTemplate.opsForValue().set(TokenKey.REDIS_KEY + entity.getUsername(), aToken, 30L, TimeUnit.MINUTES));
	            // 更新登录ip和最后登录时间
	            CompletableFuture.runAsync(() -> updateSysUserIpLoginDate(entity));
	            return ResponseData.exec(OpCode.success);
	        }
	    }
	    return ResponseData.exec(SysErrorCode.accountOrPasswordError);
	}
	
	
	@Override
	public ResponseData logoutSysUser(SysUserEntity sysUserEntity) {
	    String token = request.getHeader("token");
	    if (StringUtil.isNotEmpty(token)) {
	        // 从token中解析出用户信息
	        SysUserEntity entity = TokenUtil.getSysUserEntity(token);
	        // 取前缀和用户名为redis key
	        String redisKey = TokenKey.REDIS_KEY + entity.getUsername();
	        if (Boolean.TRUE.equals(redisTemplate.hasKey(redisKey))) {
	            redisTemplate.delete(redisKey);
	            return ResponseData.exec(OpCode.success);
	        }
	    }
	    return ResponseData.exec(SysErrorCode.statusError);
	}
}

未登录

在这里插入图片描述
在这里插入图片描述

登录

在这里插入图片描述

登录请求(/sysUser/loginSysUser)在WebConfig中放过 token为null

在这里插入图片描述
根据用户名查用户信息
在这里插入图片描述
校验密码
在这里插入图片描述
根据用户信息生成token
放入Header中
添加token到redis中
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
其他请求需要带token到请求头中
在这里插入图片描述
请求头中token存在
redis中token存在
比较后相等
在这里插入图片描述
放行
在这里插入图片描述

注销

注销也需要带token到请求头
在这里插入图片描述
token拦截
redis比较
在这里插入图片描述
比较token
删除token
在这里插入图片描述
在这里插入图片描述

再带token访问
和redis的token比较 不同
在这里插入图片描述
在这里插入图片描述


还有个token过期的问题

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值