一、配置JWT详细教程
系统环境:
- SpringBoot后端项目,引入了Security依赖,采用了配置Security类来解决跨域问题
- 前端采用VUE框架以及axios方法
参考教程:《实践:前后端分离实现JWT登录验证,包括前、后端配置》一步步跟着做就可以了。
个人理解:
① Token的生成
- 前端:用户输入账号、密码,点击登录,前端请求发送到后端
- 后端:接收前端请求,验证账号、密码,验证成功,根据账号信息生成Token令牌,并将Token令牌返回给前端
- 前端:接收Token令牌,存储在localStorage里
② 登录状态保持与权限问题
- 前端:将localStorage里的Token令牌配置到axios的请求头中,每次axios发送请求时请求头中都会携带Token令牌
- 后端:设置拦截器,拦截前端请求,并验证前端请求的请求头中的Token令牌,验证通过则继续执行请求,验证失败则取消该请求
二、加了JWT后出现的跨域问题解析
可能原因1:
SpringBoot加了拦截器后出现的跨域问题解析
SpringBoot使用Jwt处理跨域认证问题
可能原因2:
这个问题可能是由于前端发送请求时没有将token放入请求的header中导致的。在使用JWT实现认证时,需要将生成的token存储到前端,并在每次向后端发送请求时将token放入请求header中,这样后端才能识别该用户是否已登录以及是否有权限访问该接口。
你可以在前端代码的main.js中添加一个拦截器,在请求被发送出去之前,将存储在localstorage中的token添加到请求header中,例如:
axios.interceptors.request.use(
(config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => Promise.reject(error)
);
这段代码会在每次请求前检查localstorage中是否存在token,并将其添加到请求的header中。这样,当后端接收到请求时,就可以从header中获取token并进行认证和授权操作了。
注意:为了避免XSS攻击,不要直接将token存储在localstorage中,可以考虑使用sessionStorage或者cookie等更加安全的存储方式。
这里是将《实践:前后端分离实现JWT登录验证,包括前、后端配置》里前端main.js的拦截器代码重写了一下,我是这个问题。
三、'Bearer '问题(可能是它引起的令牌失效!)
前端配置JWT时,在将Token配置到axios请求头时会在main.js用到如下代码:
// 请求拦截
axios.interceptors.request.use(
(config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = "Bearer "+token;
}
return config;
},
(error) => Promise.reject(error)
);
其中 config.headers.Authorization = "Bearer "+token; 专门添加了’Bearer ',添加’Bearer '的原因如下:
- Bearer是指OAuth 2.0协议中的一种认证方式。在使用OAuth 2.0进行API认证时,需要通过Access Token来访问受保护的资源。Bearer就是用来表明此处所使用的Access Token类型。
- 添加Bearer前缀是为了告诉服务器,我们正在使用Bearer令牌进行身份验证。服务器收到带有Bearer令牌的请求后,会解析出令牌并对其进行验证。如果验证通过,则允许请求对受保护的资源进行操作。
- 因此,在config.headers.Authorization = "Bearer "+token;中,Bearer是指定了使用的Access Token的类型,而token则是具体的Access Token值。
所以,后端解析请求头中的Token时,得到的是带有Bearer 的Token,然而验证Token、解析Token都需要“干净”的Token,即没有Bearer 的Token,所以如下需要把Bearer 去除:
①验证Token方法
public static Map<String, Claim> verifyToken(String token)throws Exception{
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
DecodedJWT jwt = null;
// 删除前7个字符:将Bearer 删除得到“干净”的token
token = token.substring(7);
try {
jwt = verifier.verify(token);
}catch (Exception e){
throw new RuntimeException("凭证失效");
}
return jwt.getClaims();
}
解析Token方法
@Override
public List<UserInfoDto> getUserInfo(HttpServletRequest request) {
// 获取请求头中的Token值
String authHeader = request.getHeader("Authorization");
String token = "";
if (authHeader != null && authHeader.startsWith("Bearer ")) {
// 去除‘Bearer ’
token = authHeader.substring(7);
}
// 获取Token中用户email
String email = JwtUtil.parseToken(token).get("email").asString();
UserInfoDto dto = new UserInfoDto();
dto.setEmail(email);
// 查询用户信息
List<UserInfoDto> ressultList = getUserInfo_private(dto);
return ressultList;
}