shiro整合springBoot后登录一直失败的原因
最后发现是存入数据库的密码密文在shiro比较之前会进行一次base64的转换
上代码
shiro配置
@Configuration
public class ShiroConfig {
/**
* 加密算法
* @return
*/
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher(){
//加密对象
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
//加密方法
matcher.setHashAlgorithmName("md5");
//加密次数
matcher.setHashIterations(2);
//加密编码方式
matcher.setStoredCredentialsHexEncoded(false);
return matcher;
}
/**
* 自定义realm
* @return
*/
@Bean
public MyRealm myRealm(){
MyRealm myRealm = new MyRealm();
myRealm.setCredentialsMatcher(hashedCredentialsMatcher());
return myRealm;
}
/**
* 安全管理器
* @return
*/
@Bean
public SecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myRealm());
return securityManager;
}
/**
* shiro
* @return
*/
@Bean
public ShiroFilterFactoryBean shiroFilter(){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager());
Map<String,String> filterChainDefinitionMap = new HashMap<>(16);// 配置不会被拦截的链接 顺序判断,因为前端模板采用了 thymeleaf,
// 这里不能直接使用 ("/static/**", "anon")来配置匿名访问,必须配置到每个静态目录
filterChainDefinitionMap.put("/css/**", "anon");
filterChainDefinitionMap.put("/fonts/**", "anon");
filterChainDefinitionMap.put("/img/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
//配置退出 过滤器,其中的具体的退出代码 Shiro 已经替我们实现了
filterChainDefinitionMap.put("/logout", "logout");
// 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
// authc:所有 url 都必须认证通过才可以访问; anon:所有 url 都都可以匿名访问-->
filterChainDefinitionMap.put("/user/login","anon");
filterChainDefinitionMap.put("/user/register","anon");
filterChainDefinitionMap.put("/user/login_page","anon");
//所有请求都认证
filterChainDefinitionMap.put("/**", "authc");
// 如果不设置默认会自动寻找 Web 工程根目录下的"/login.jsp"页面
shiroFilterFactoryBean.setLoginUrl("/user/login");
// 登录成功后要跳转的链接
shiroFilterFactoryBean.setSuccessUrl("/index");
//未授权界面;
shiroFilterFactoryBean.setUnauthorizedUrl("/error");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
/**
* 管理shirobean的生命周期
* @return
*/
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
return new LifecycleBeanPostProcessor();
}
/**
* aop注解支持
* @param securityManager
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
/**
* aop生效
* @return
*/
@Bean
public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator(){
DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
autoProxyCreator.setProxyTargetClass(true);
return autoProxyCreator;
}
}
自定义realm
@Component
@SuppressWarnings("all")
public class MyRealm extends AuthorizingRealm {
@Autowired
EmployeeMapper employeeMapper;
PasswordService passwordService = new DefaultPasswordService();
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
String userName = (String) principalCollection.getPrimaryPrincipal();
SimpleAuthorizationInfo simpleAuthenticationInfo = new SimpleAuthorizationInfo();
return simpleAuthenticationInfo;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String employeeName = (String) authenticationToken.getPrincipal();
String passWord = null;
if (StringUtils.isNumeric(employeeName)&&employeeName.length()!=11) { //判断为数字且不是手机号
Integer employeeId = Integer.valueOf(employeeName);
passWord = getPwdByid(employeeId);
}else if(StringUtils.isNumeric(employeeName)&&employeeName.length()==11){ //判断为手机号
passWord = getPwdByPhone(employeeName);
}else { //其他所有情况判断为邮箱
passWord = getPwdByEmail(employeeName);
}
if (passWord==null){
return null;
}
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(employeeName,passWord,getName());
return info;
}
/**
* 根据id查密码
* @param employeeId
* @return
*/
public String getPwdByid(int employeeId){
Employee employee = employeeMapper.selectByPrimaryKey(employeeId);
if (employee==null){
return null;
}
return employee.getPassword();
}
/**
* 根据手机号查密码
* @param phone
* @return
*/
public String getPwdByPhone(String phone){
Employee employee = employeeMapper.selectByPhone(phone);
if (employee==null){
return null;
}
return employee.getPassword();
}
/**
* 根据邮箱查密码
* @param email
* @return
*/
public String getPwdByEmail(String email){
Employee employee = employeeMapper.selectByEmail(email);
if (employee==null){
return null;
}
return employee.getPassword();
}
public Employee getEmpByPhone(String phone){
Employee employee = employeeMapper.selectByPhone(phone);
if (employee==null){
return null;
}
return employee;
}
public int register(Employee employee){
employee.setPassword(new Md5Hash(employee.getPassword(),null,2).toString());
employeeMapper.insert(employee);
return 1;
}
在存入数据库时调用加密时用的 toString() 方法
public int register(Employee employee){
employee.setPassword(new Md5Hash(employee.getPassword(),null,2).toString());
employeeMapper.insert(employee);
return 1;
}
存入数据库的时 123456 加密后 用toString获取的密文
此时登录一直无法通过
toString() 和 Hex 要一致
toBase64() he 上面一致
最后导致始终无法登录