前言
- 本篇博客主要解决
shiro
在前后端分离项目应用中,结合jwt
进行鉴权时,出现的第一次请求接口报错404问题
查询网上资料,大部分是前后端不分离的解决方法,或是只描述问题并不给出解决方法,本文针对前后端分离情况,使用了 jwt 鉴权后,第一次请求接口不执行 shiro 的 AuthorizationInfo 方法,给出一个简便的解决方法。
白嫖容易,创作不易,若大家认为有用,学到知识,不妨点个赞
博客原创,转载请注明出处
背景描述
项目采用前后端分离模式,使用 SpringBoot + Shiro + Jwt 进行前后端分离鉴权,使用Swagger进行测试
此时登录通过校验用户名密码后返回 token,登录接口已在shiro配置中放行
public R login(@Parameter(description = "用户名") @PathVariable String username, @Parameter(description = "密码") @PathVariable String password){
User user = null;
try {
user = userService.findByUserName(username);
} catch (Exception e) {
e.printStackTrace();
return R.error().message("用户名或密码错误!");
}
if (user == null) {
return R.error().message("用户名或密码错误!");
}
if (!user.getPassword().equals(password)) {
return R.error().message("用户名或密码错误!");
}
String token = TokenUtils.getToken(user.getUserId());
return R.ok().data("token",token);
}
问题描述
-
启动项目后,先进行登录
-
随意选择一个接口进行测试
-
结果出现404,但第二次就可正常执行
-
查看后台日志可以发现,确实执行了认证方法
-
继续查看发现,执行完认证方法后,并不执行授权方法
以下为认证方法部分代码//密码认证shiro做,由于该项目密码没有加密加盐,所以调用的是这个简单构造方法 SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, useToken.getPrincipal().toString(), this.getName()); System.out.println("=======================密码验证!"); return info;
解决过程
查询各种博客资料后,发现了:shiro中的授权方法,即 AuthorizationInfo 方法,并不是执行认证后就会执行,而是访问限制资源时才执行。
这时我们回想我们的问题:登录后,第一次请求接口只认证不授权,但第二次后便恢复正常,第一次请求的接口也是限制资源,那为什么会出现这样的问题?
这时我们回想,在前后端不分离的项目中,没有使用 jwt 登录鉴权,这时的 shiro 登录是需要用到 subject.login 方法进行主动登录,而在前后端分离的项目中,我们并不需要这样进行,只需要在认证时校验用户即可。
由此我猜想,或许跟这个问题有关。
解决方法
直接在登录时采用原来的 subject.login 登录方式
public R login(@Parameter(description = "用户名") @PathVariable String username, @Parameter(description = "密码") @PathVariable String password){
User user = null;
try {
user = userService.findByUserName(username);
} catch (Exception e) {
e.printStackTrace();
return R.error().message("用户名或密码错误!");
}
if (user == null) {
return R.error().message("用户名或密码错误!");
}
if (!user.getPassword().equals(password)) {
return R.error().message("用户名或密码错误!");
}
String token = TokenUtils.getToken(user.getUserId());
Subject subject = SecurityUtils.getSubject();
subject.login(new AuthToken(token));
return R.ok().data("token",token);
}
由此测试,加入这句登录代码后,在登录的时候便执行了一次认证,接着请求第二个限制资源时,便可以正常进行认证授权了。
由此猜测,shiro 的认证授权,是需要第一次认证后,shiro才能“记住这个用户”。因此以subject.login 方法来执行一次认证即可。
本人技术水平有限,难免出现逻辑不清晰或解释错误等问题,请大家包涵!可在评论区反馈