起因:项目之前是消费者单Realm验证,因为新加了商家、管理员。所以需要多Realm验证。
过程:参考博客大佬中的步骤
1新建了UsernamePasswordToken的子类LoginsToken,主要用来标识当前登录类型
public class LoginsToken extends UsernamePasswordToken {
//logins type
private String loginType;
public LoginsToken(final String username,final String password,final String loginType){
super(username,password);
this.loginType=loginType;
}
public LoginsToken(final String username,final char[] password,
String loginType) {
super(username, password);
this.loginType=loginType;
}
public String getLoginType() {
return loginType;
}
public void setLoginType(String loginType) {
this.loginType = loginType;
}
}
2.新建了ModularRealmAuthenticator的子类LoginsModularRealmAuthenticator,主要用来分发realm
public class LoginsModularRealmAuthenticator extends ModularRealmAuthenticator {
private static Logger logger=LoggerFactory.getLogger(LoginsModularRealmAuthenticator.class);
@Override
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken){
logger.info("分发realm:----------------------------");
//判断getRealm()是够返回为空
super.assertRealmsConfigured();
//强制转换回自定义的loginsToken
LoginsToken loginsToken=(LoginsToken) authenticationToken;
//登录类型
String loginType=loginsToken.getLoginType();
//所有Realm
Collection<Realm> realms=getRealms();
//登录类型获取对应的
Collection<Realm> typeRealms = new ArrayList<>();
for (Realm realm : realms) {
if (realm.getName().contains(loginType))
typeRealms.add(realm);
}
logger.info("对用的reaml:-------------:"+typeRealms.toString());
// 判断是单Realm还是多Realm
if (typeRealms.size() == 1){
logger.info("doSingleRealmAuthentication() execute "+typeRealms.iterator().next());
/* AuthenticationInfo authenticationInfo = doSingleRealmAuthentication(new BusinessRealm(), loginsToken);*/
return doSingleRealmAuthentication(typeRealms.iterator().next(),loginsToken);
}
else
return doMultiRealmAuthentication(typeRealms,loginsToken);
}
3.新建自定义Realm
public class UserRealm extends AuthorizingRealm {
private static Logger logger=LoggerFactory.getLogger(UserRealm.class);
@Autowired
private HomeService homeService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//把AuthenticationToken转换为LoginsToken
LoginsToken loginsToken= (LoginsToken) authenticationToken;
//获取登录名
String loginname=loginsToken.getPrincipal()+"";
logger.info("loginname:-------"+loginname);
//查询用户信息
User user=homeService.getByLoginName(loginname);
logger.info("user:-------"+user);
if(user!=null){
// 根据用户的情况,来构建AuthenticationInfo对象并返回,通常使用的实现类为SimpleAuthenticationInfo
//验证身份
SimpleAuthenticationInfo authenticationInfo=new SimpleAuthenticationInfo(user,user.getPassword(),"xxx");
logger.info("用户返回对象:--------"+authenticationInfo);
return authenticationInfo;
}
return null;
}
}
4.配置文件配置不同登录人的type的
#登录人的type
login.user=User
login.business=Business
login.admin=Admin
5.修改controller代码
@RequestMapping(value = "/blogined",method = RequestMethod.POST)
public String login(Business business , Model model){
//1 获取Subject
Subject subject= SecurityUtils.getSubject();
/* if(!subject.isAuthenticated()){*/
//创建令牌,封装用户数据
LoginsToken token=new LoginsToken(business.getBrealname(),business.getBpassword(),BusinessType);;
try {
subject.login(token);
}catch (UnknownAccountException e){
model.addAttribute("errorMsg","登录名错误,登录失败");
return "login";
}catch (IncorrectCredentialsException e){
model.addAttribute("errorMsg","密码错误,登陆失败");return "login";
}
/* }*/
return "/business/index";
6.配置ShiroCofing @Bean给容器中添加组件
Authentication failed for token submission报错原因
参考文章:
[配置多Realm](https://blog.csdn.net/sinat_35626559/article/details/94553393)
[ Authentication failed for token submission错误启发](https://www.cnblogs.com/Z-share/p/11758176.html)