文章目录
1.需求
原先的user表数据。相当于多个部门, 每个部门都有自己登录地址,其实用的功能都一样。 不想多布置服务器,但登录地址又不一样。找了网上不少内容参考终于搞出来了。
2. 登录代码修改
用户类型枚举类
loginTypeEnums
重写 UsernamePasswordToken
public class UserPasswordToken extends UsernamePasswordToken {
private static final long serialVersionUID = -1L;
private String loginType;
public UserPasswordToken(String username, char[] password,String loginType) {
super(username, password);
this.loginType = loginType;
}
public String getLoginType() {
return loginType;
}
public void setLoginType(String loginType) {
this.loginType = loginType;
}
public static long getSerialVersionUID() {
return serialVersionUID;
}
}
根据loginType 写对应的realm
Xxxx extends AuthorizingRealm 基本一样就名字不一样 ModularRealmAuthenticator中需要根据loginTpe 判断realm
重写ModularRealmAuthenticator, 根据提交的loginType选择realm
public class ModelRealmAuthenticator extends ModularRealmAuthenticator {
@Override
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken)
throws AuthenticationException {
assertRealmsConfigured();
UserPasswordToken customizedToken = (UserPasswordToken) authenticationToken;
String loginType = customizedToken.getLoginType();
Collection<Realm> realms = getRealms();
Collection<Realm> loginRealms = new ArrayList<>();
AuthenticationException authenticationException = null;
for (Realm realm : realms) {
if (realm.getName().contains(loginType)) {
AuthenticationInfo info = null;
try {
info = realm.getAuthenticationInfo(authenticationToken);
} catch (AuthenticationException e) {
//为了抓自定义的AccountException
authenticationException = e;
}
loginRealms.add(realm);
}
}
if(authenticationException != null){
throw authenticationException;
}
if (loginRealms.size() == 1)
return doSingleRealmAuthentication(loginRealms.iterator().next(), customizedToken);
else
return doMultiRealmAuthentication(loginRealms, customizedToken);
}
}
根据loginType的类型写重写对应的FormAuthenticationFilter 登录操作
public class UserFormAuthenticationFilter extends FormAuthenticationFilter {
public static final String LOGIN_TYPE = loginTypeEnums.WEB.getType();
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
if(request.getAttribute(getFailureKeyAttribute()) != null) {
return true;
}
return super.onAccessDenied(request, response, mappedValue);
}
@Override
protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request,
ServletResponse response) throws Exception {
WebUtils.getAndClearSavedRequest(request);
WebUtils.redirectToSavedRequest(request, response, "/");// 页面跳转到首页
return false;
}
@Override
protected UserPasswordToken createToken(ServletRequest request, ServletResponse response) {
String username = getUsername(request);
String password = getPassword(request);
return new UserPasswordToken(username, password.toCharArray(), LOGIN_TYPE);
}
@Override
protected void redirectToLogin(ServletRequest request, ServletResponse response) throws IOException {
String loginUrl = "/user/login";
WebUtils.issueRedirect(request, response, loginUrl);
}
}
3. 登出代码
public class MyLogoutFilter extends LogoutFilter {
private static final Logger log = LoggerFactory.getLogger(LogoutFilter.class);
@Override
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
Subject subject = getSubject(request, response);
Session session = subject.getSession();
User user = (User) session.getAttribute(Constants.CURRENT_USER);
if (user != null) {
//realm登录的时候把userType放入session中了
String userType = (String) session.getAttribute(user.getUsername());
if (LoginType.JISHU.getType().equals(userType)) {
this.setRedirectUrl("/jishu/login");
} if (StringUtils.isEmpty(userType)) {
this.setRedirectUrl(this.DEFAULT_REDIRECT_URL);
}
}
String redirectUrl = getRedirectUrl(request, response, subject);
try {
subject.logout();
} catch (SessionException ise) {
log.debug("Encountered session exception during logout. This can generally safely be ignored.", ise);
}
//设置登出后的跳转地址
issueRedirect(request, response, redirectUrl);
return false;
}
}
4. 超时时跳转处理
用的cookie 携带 loginType .
- 不同登录login操作时设置cookie中的logintType
- 重写AccessControlFilter的onAccessDenied(ServletRequest request, ServletResponse response) 方法判断未登录时cookie里loginType的类型来设置this.setLoginUrl(xxx)返回不同的登录地址.
5. 配置spring-shiro.xml
配置多个realm ,DefaultWebSecurityManager 中realms. 重写的filter ,ShiroFilterFactoryBean 引入重写的filter