前言
在进行身份认证时,一般会考虑两种方案,一是使用session,二是使用jwt。而使用session这个方案通常会产生一些比较棘手的问题,那就是跨域。而使用jwt则可以完美避开跨域的问题。下面我来实际使用jwt方案。
后端
一、准备依赖
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.9.0</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20190722</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.1</version>
</dependency>
二、建表
create table if not exists token
(
id bigint auto_increment comment 'id' primary key,
token varchar(512) not null comment 'token'
);
三、操作token
TokenMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lzj.qqbackend.mapper.TokenMapper">
<resultMap id="BaseResultMap" type="com.lzj.qqbackend.model.bean.Token">
<id property="id" column="id" jdbcType="BIGINT"/>
<result property="token" column="token" jdbcType="VARCHAR"/>
</resultMap>
<sql id="Base_Column_List">
id,token
</sql>
<insert id="insertOrUpdate">
INSERT INTO qq.token (id, token)
VALUES (#{id}, #{token})
<if test="id != null">
ON DUPLICATE KEY UPDATE
token = #{token}
</if>
</insert>
</mapper>
TokenMapper
package com.lzj.qqbackend.mapper;
import com.lzj.qqbackend.model.bean.Token;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Select;
/**
* @author 赖志军
* @description 针对表【token(token表)】的数据库操作Mapper
* @createDate 2023-11-24 17:04:13
* @Entity com.lzj.qqbackend.model.bean.Token
*/
public interface TokenMapper extends BaseMapper<Token> {
@Select("select id from 数据库名称.token where token = #{token}")
Long getTokenId(String token);
void insertOrUpdate(Long id,String token);
}
实体类Token
package com.lzj.qqbackend.model.bean;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import lombok.Data;
/**
* token表
* @TableName token
*/
@TableName(value ="token")
@Data
public class Token implements Serializable {
/**
* id
*/
@TableId
private Long id;
/**
* token字符串
*/
private String token;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}
!!!注意上面的代码需要根据自己的项目进行修改。就是生成一个操作token表的mapper。这一部分代码也可以不使用,也可使用jwt。这个代码可以用来无感刷新token,这里就不多说了。
四、token工具类
package com.lzj.sweetsManger.utils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.google.gson.Gson;
import com.lzj.sweetsManger.mapper.TokenMapper;
import com.lzj.sweetsManger.model.vo.UserVO;
import javax.annotation.Resource;
import java.util.Date;
public class TokenUtils {
//token到期时间10小时
private static final long EXPIRE_TIME= 10*60*60*1000;
//密钥盐
private static final String TOKEN_SECRET="ljdyaishijin**3nkjnj??";
@Resource
private TokenMapper tokenMapper;
/**
* 生成token
* @param userVO
* @return
*/
public static String sign(UserVO userVO){
String token=null;
try {
Date expireAt=new Date(System.currentTimeMillis()+EXPIRE_TIME);
Gson gson = new Gson();
String userVoJSON = gson.toJson(userVO);
token = JWT.create()
//发行人
.withIssuer("auth0")
//存放数据
.withClaim("userVO",userVoJSON)
//过期时间
.withExpiresAt(expireAt)
.sign(Algorithm.HMAC256(TOKEN_SECRET));
} catch (IllegalArgumentException| JWTCreationException je) {
}
return token;
}
/**
* token验证
* @param token
* @return
*/
public static Boolean verify(String token){
try {
//创建token验证器
JWTVerifier jwtVerifier=JWT.require(Algorithm.HMAC256(TOKEN_SECRET)).withIssuer("auth0").build();
DecodedJWT decodedJWT=jwtVerifier.verify(token);
} catch (IllegalArgumentException | JWTVerificationException e) {
//抛出错误即为验证不通过
return false;
}
return true;
}
//获取存储的用户信息
public static UserVO getUserVO(String token){
try {
DecodedJWT jwt = JWT.decode(token);
String userVOStr = jwt.getClaim("userVO").asString();
Gson gson = new Gson();
return gson.fromJson(userVOStr,UserVO.class);
} catch (JWTDecodeException e) {
return null;
}
}
}
五、使用
在用户登录时,使用token工具类中的sign方法生成token并返回token给前端。
前端
一、配置axios
在登录成功时,存储token, localStorage.setItem(“token”,res.data.token)
axios.defaults.headers.common['Authorization'] = localStorage.getItem("token");
总结
ok了,有不懂的,可以在评论区问我。