shiro管理多登录入口配置,手机端登录与网页端登录
1、2个Realm:分别为手机端、网页端的
/**
* 自定义MobileRealm .
*/
public class MobileRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
return null;
}
@Override
// 验证的核心方法
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String userCode = (String) token.getPrincipal();
UsernamePasswordToken usernamePassword = (UsernamePasswordToken) token;
char[] passWord = usernamePassword.getPassword();
if (StringUtil.isEmpty(userCode)) {
throw new UserNameNullException();// 账号为空
}
if (StringUtil.isEmpty(passWord)) {
throw new PassWordNullException();// 密码为空
}
// 根据登录名查询操作员
Admin operator = null;
try {
operator = adminService.getAdminUserByUserCode(userCode);
} catch (Exception e) {
e.printStackTrace();
}
if (operator == null) {
throw new UnknownAccountException();// 没找到帐号
}
if (!Constants.UserLockStatus.UNLOCK.equals(operator.getLock_status())) {
throw new LockedAccountException(); // 账号锁定或者不是生效状态
}
if (!Constants.UserStatus.OPEN.equals(operator.getUser_status())) {
throw new LockedAccountException(); // 账号锁定或者不是生效状态
}
// 交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(operator.getUser_name(), // 登录名
operator.getUser_pswd(), // 密码
getName() // realm name
);
return authenticationInfo;
}
@Override
public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
super.clearCachedAuthorizationInfo(principals);
}
@Override
public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
super.clearCachedAuthenticationInfo(principals);
}
@Override
public void clearCache(PrincipalCollection principals) {
super.clearCache(principals);
}
public void clearAllCachedAuthorizationInfo() {
getAuthorizationCache().clear();
}
public void clearAllCachedAuthenticationInfo() {
getAuthenticationCache().clear();
}
public void clearAllCache() {
clearAllCachedAuthenticationInfo();
clearAllCachedAuthorizationInfo();
}
}
/**
* 自定义realm .
*
*/
public class WebRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
return null;
}
@Override
// 验证的核心方法
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String userCode = (String) token.getPrincipal();
UsernamePasswordToken usernamePassword = (UsernamePasswordToken) token;
char[] passWord = usernamePassword.getPassword();
if (StringUtil.isEmpty(userCode)) {
throw new UserNameNullException();// 账号为空
}
if (StringUtil.isEmpty(passWord)) {
throw new PassWordNullException();// 密码为空
}
// 根据登录名查询操作员
Admin operator = null;
try {
operator = adminService.getAdminUserByUserCode(userCode);
} catch (Exception e) {
e.printStackTrace();
}
if (operator == null) {
throw new UnknownAccountException();// 没找到帐号
}
if (!Constants.UserLockStatus.UNLOCK.equals(operator.getLock_status())) {
throw new LockedAccountException(); // 账号锁定或者不是生效状态
}
if (!Constants.UserStatus.OPEN.equals(operator.getUser_status())) {
throw new LockedAccountException(); // 账号锁定或者不是生效状态
}
// 交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(operator.getUser_name(), // 登录名
operator.getUser_pswd(), // 密码
getName() // realm name
);
return authenticationInfo;
}
@Override
public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
super.clearCachedAuthorizationInfo(principals);
}
@Override
public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
super.clearCachedAuthenticationInfo(principals);
}
@Override
public void clearCache(PrincipalCollection principals) {
super.clearCache(principals);
}
public void clearAllCachedAuthorizationInfo() {
getAuthorizationCache().clear();
}
public void clearAllCachedAuthenticationInfo() {
getAuthenticationCache().clear();
}
public void clearAllCache() {
clearAllCachedAuthenticationInfo();
clearAllCachedAuthorizationInfo();
}
}
2、2个自定义form表单认证过滤器:分别为手机端、网页端的
/**
* 自定义webform表单认证过滤器<br/>
*/
public class WebFormAuthenticationFilter extends FormAuthenticationFilter {
public static final String LOGIN_TYPE = LoginType.WEB.toString();
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue)
throws Exception {
Subject subject = SecurityUtils.getSubject();
Session session = subject.getSession();
//将版本号保存到session中
if (session.getAttribute(Constants.SESSION_VERSION) == null) {
session.setAttribute(Constants.SESSION_VERSION,Constants.SESSION_VERSION_NO);
}
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, "/index");// 页面跳转到首页
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);
}
}
/**
* 自定义mobileform表单认证过滤器<br/>
*/
public class MobileFormAuthenticationFilter extends FormAuthenticationFilter {
public static final String LOGIN_TYPE = LoginType.MOBILE.toString();
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue)
throws Exception {
Subject subject = SecurityUtils.getSubject();
Session session = subject.getSession();
//将版本号保存到session中
if (session.getAttribute(Constants.SESSION_VERSION) == null) {
session.setAttribute(Constants.SESSION_VERSION,Constants.SESSION_VERSION_NO);
}
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, "/mobile/index");// 页面跳转到首页
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);
}
}
3、登录方式区分
(1)登录类型定义
public enum LoginType {
WEB("Web"), MOBILE("Mobile");
private String type;
private LoginType(String type) {
this.type = type;
}
@Override
public String toString() {
return this.type.toString();
}
}
(2)添加logintype
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;
}
}
(3)判断登录
/**
* 自定义Authenticator
* 注意,对应Realm的类名要分别包含字符串“Mobile”或“Web”,
*不能一个类名同时包含两个字符串,否则无法选择Realm
* @author yigai
*
*/
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<>();
for (Realm realm : realms) {
if (realm.getName().contains(loginType))
loginRealms.add(realm);
}
if (typeRealms.size() == 1)
return doSingleRealmAuthentication(loginRealms.iterator().next(), customizedToken);
else
return doMultiRealmAuthentication(loginRealms, customizedToken);
}
}
4、xml配置
<!-- 自定义的web Realm实现 -->
<bean id="webRealm" class="com.shiro.WebRealm">
<property name="credentialsMatcher" ref="credentialsMatcher" />
<property name="cachingEnabled" value="false" />
<!--<property name="authorizationCachingEnabled" value="true"/> -->
<!--<property name="authorizationCacheName" value="authorizationCache"/> -->
</bean>
<!-- 自定义的mobile Realm实现 -->
<bean id="mobileRealm" class="com.shiro.MobileRealm">
<property name="credentialsMatcher" ref="credentialsMatcher" />
<property name="cachingEnabled" value="false" />
<!--<property name="authorizationCachingEnabled" value="true"/> -->
<!--<property name="authorizationCacheName" value="authorizationCache"/> -->
</bean>
<!-- 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="authenticator" ref="authenticator" />
<!-- 可以配置多个Realm,realms属性被赋值给ModelRealmAuthenticator的realms属性 -->
<property name="realms">
<list>
<ref bean="webRealm" />
<ref bean="mobileRealm"/>
</list>
</property>
</bean>
<!-- 配置使用自定义认证器,实现多Realm认证-->
<bean id="authenticator" class="com.shiro.ModelRealmAuthenticator">
<property name="authenticationStrategy">
<bean class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"></bean>
</property>
</bean>
<!-- 基于Form表单的身份验证过滤器 -->
<bean id="authcFilter"
class="com.shiro.FormAuthenticationFilter">
<!-- from表达提交参数的属性命名 -->
<property name="usernameParam" value="userAccount" />
<property name="passwordParam" value="password" />
<!--<property name="rememberMeParam" value="rememberMe" /> -->
<property name="loginUrl" value="/login" />
<property name="failureKeyAttribute" value="shiroLoginFailure" />
</bean>
<bean id="mobileFilter" class="com.shiro.MobileFormAuthenticationFilter">
<!-- from表达提交参数的属性命名 -->
<property name="usernameParam" value="userAccount" />
<property name="passwordParam" value="password" />
<!--<property name="rememberMeParam" value="rememberMe" /> -->
<property name="loginUrl" value="/mobile/login" />
<property name="failureKeyAttribute" value="shiroLoginFailure" />
</bean>
<!-- 验证码验证过滤器 -->
<bean id="captchaValidateFilter"
class="com.shiro.CaptchaValidateFilter">
<property name="captchaEbabled" value="true" />
<property name="captchaParam" value="captchaCode" />
<property name="failureKeyAttribute" value="shiroLoginFailure" />
</bean>
<!-- Shiro主过滤器本身功能十分强大,其强大之处就在于它支持任何基于URL路径表达式的、自定义的过滤器的执行 -->
<!-- Web应用中,Shiro可控制的Web请求必须经过Shiro主过滤器的拦截,Shiro对基于Spring的Web应用提供了完美的支持 -->
<bean id="shiroFilter"
class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 登录controller的mapper地址 -->
<property name="loginUrl" value="/login" />
<!-- <property name="successUrl" value="/index"/> -->
<property name="filters">
<util:map>
<entry key="captchaValidate" value-ref="captchaValidateFilter" />
<entry key="authc" value-ref="authcFilter" />
<entry key="mobile" value-ref="mobileFilter" />
</util:map>
</property>
<property name="filterChainDefinitions">
<value>
/js/**=anon
/images/**=anon
/login =captchaValidate,authc
/mobile/login =captchaValidate,mobile
/logout=authc
/index=authc
/mobile/index=mobile
/** = authc
/** = mobile
</value>
</property>
5、2个controller:
(1)WebController
@RequestMapping(value = "/", method = { RequestMethod.POST, RequestMethod.GET })
public String index() {
return "redirect:/login";
}
@RequestMapping(name = "首页", value = "/index", produces = "text/html;charset=UTF-8")
public String index(Model model) {
return "adminUser/index";
}
/**
*
* @param request
* @param model
* @return
*/
@RequestMapping(value = "/login")
public String login(HttpServletRequest request, Model model) {
logger.info("login start.");
String exceptionClassName = (String) request.getAttribute("shiroLoginFailure");
String error = null;
...
// 如果没有错误 并且 session中的AdminUser不为空
if (StringUtils.isEmpty(error) && null != session.getAttribute(Constants.SESSION_KEY_ADMIN_USER)) {
logger.info("login end.");
return "redirect:/index";
}
logger.info("login end.");
return "system/login";
}
(2)MobileController
@RequestMapping(value = "/mobile", method = { RequestMethod.POST, RequestMethod.GET })
public String index() {
return "redirect:/mobile/login";
}
@RequestMapping(name = "首页", value = "/index", produces = "text/html;charset=UTF-8")
public String index(Model model) {
return "/mobile/index";
}
/**
*
* @param request
* @param model
* @return
*/
@RequestMapping(value = "/mobile/login")
public String login(HttpServletRequest request, Model model) {
logger.info("login start.");
String exceptionClassName = (String) request.getAttribute("shiroLoginFailure");
String error = null;
...
// 如果没有错误 并且 session中的AdminUser不为空
if (StringUtils.isEmpty(error) && null != session.getAttribute(Constants.SESSION_KEY_ADMIN_USER)) {
logger.info("login end.");
return "redirect:/mobile/index";
}
logger.info("login end.");
return "mobile/login";
}
到这就可以完成多登录入口配置,稍后上传详细文件资源