在springboot中shiro整合mybatis,访问的时候报了500的错误,如下图所示
首先,在此之前,我的项目中,mybatis和springboot的整合是成功的,并且能够正常运行的,其次shiro和springboot也是。所以说问题可能出现在mybatis和shiro版本的问题上,然后降版本,界面变成下面这样:
如果没有发生变化的话,可以看看首页和登录页的html文件那里的头部有没有以下代码段
<html lang="en" xmlns:th="http://www.thymeleaf.org">
这个时候可以看出来,是抛出了AuthenticationException
异常,出现这个异常的原因是因为身份验证出错了,就是说代码验证出错了。然后检查了一遍代码,发现代码没有问题,逐步debug,发现,用户名的访问时正常的,但是密码这里有问题,所以把重点放在密码验证这里。
package com.kuang.config;
import com.kuang.Service.UserService;
import com.kuang.pojo.User;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
public class UserRealm extends AuthorizingRealm {
@Autowired
UserService userService;
@Override
//授权
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("执行了=>授权doGetAuthorizationInfo");
return null;
}
@Override
//认证
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("执行了=>认证doGetAuthenticationInfo");
UsernamePasswordToken userToken = (UsernamePasswordToken) token;
User user = userService.queryUserByName(userToken.getUsername());
if(user==null){//没有这个人
return null;//抛出异常UnknownAccountException
}
return new SimpleAuthenticationInfo("",user.getPwd(),"");
}
}
首先,User类里面用的是AllArgsConstructor注解方法来实现有参构造的,其实和自己重写get和set一样,可以看到有一个getpassword和setpassword的方法,按我们的思路来看,我们这里调用的就是User类下面的这两个方法
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private String password;
}
//有参构造
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
,但是我们看了下shiro的源码可以发现,在shiro中也有getpassword和setpassword这两个方法,而在我们将shiro和mybatis整合的时候,这两个类其实是被注入到一起的,这个时候,相当于两个getpassword方法重了,鉴于shiro拦截器的本身特性,我们调用的都会是shiro中的getpassword方法,而不是User类的。
public class UsernamePasswordToken implements HostAuthenticationToken, RememberMeAuthenticationToken {
private String username;
private char[] password;
private boolean rememberMe;
private String host;
public UsernamePasswordToken(String username, char[] password, boolean rememberMe, String host) {
this.rememberMe = false;
this.username = username;
this.password = password;
this.rememberMe = rememberMe;
this.host = host;
}
.
.
.
public char[] getPassword() {
return this.password;
}
public void setPassword(char[] password) {
this.password = password;
}
所以在这里User类的全参构造不能用注解AllArgsConstructor来实现,或者你自己把这个注解的改一下也行,我是直接重写了get和set方法
public String getPwd() {
return password;
}
public void setpwd(String password) {
this.password = password;
}
这个时候我的问题就得到了解决。
此外在这里也可以发现,此时user调用的时候还是可以调到两个get的方法,即getPwd()和getPassword(),这也验证了前面自己思路的准确性。