多realm登录方式
This commit is contained in:
parent
d4b353d8f2
commit
47862f692d
|
|
@ -2,6 +2,9 @@ package com.ruoyi.web.controller.system;
|
|||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.ruoyi.framework.shiro.LoginType;
|
||||
import com.ruoyi.framework.shiro.UserToken;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||
|
|
@ -39,22 +42,9 @@ public class SysLoginController extends BaseController
|
|||
@ResponseBody
|
||||
public AjaxResult ajaxLogin(String username, String password, Boolean rememberMe)
|
||||
{
|
||||
UsernamePasswordToken token = new UsernamePasswordToken(username, password, rememberMe);
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
try
|
||||
{
|
||||
subject.login(token);
|
||||
return success();
|
||||
}
|
||||
catch (AuthenticationException e)
|
||||
{
|
||||
String msg = "用户或密码错误";
|
||||
if (StringUtils.isNotEmpty(e.getMessage()))
|
||||
{
|
||||
msg = e.getMessage();
|
||||
}
|
||||
return error(msg);
|
||||
}
|
||||
// UsernamePasswordToken token = new UsernamePasswordToken(username, password, rememberMe);
|
||||
UserToken token = new UserToken(username, password, rememberMe, LoginType.USER_PASSWORD);
|
||||
return shiroLogin(token);
|
||||
}
|
||||
|
||||
@GetMapping("/unauth")
|
||||
|
|
@ -62,4 +52,35 @@ public class SysLoginController extends BaseController
|
|||
{
|
||||
return "error/unauth";
|
||||
}
|
||||
|
||||
/**
|
||||
* 手机验证码登录
|
||||
* 注:由于是demo演示,此处不添加发送验证码方法;
|
||||
* 正常操作:发送验证码至手机并且将验证码存放在redis中,登录的时候比较用户穿过来的验证码和redis中存放的验证码
|
||||
*
|
||||
* @param phone
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/phoneLogin")
|
||||
@ResponseBody
|
||||
public AjaxResult phoneLogin(String phone, String code) {
|
||||
// 此处phone替换了username,code替换了password
|
||||
UserToken token = new UserToken(phone, code, LoginType.USER_PHONE);
|
||||
return shiroLogin(token);
|
||||
}
|
||||
|
||||
public AjaxResult shiroLogin(UserToken token) {
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
try {
|
||||
subject.login(token);
|
||||
return success();
|
||||
} catch (AuthenticationException e) {
|
||||
String msg = "用户或密码错误";
|
||||
if (StringUtils.isNotEmpty(e.getMessage())) {
|
||||
msg = e.getMessage();
|
||||
}
|
||||
return error(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,12 @@
|
|||
package com.ruoyi.framework.config;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import javax.servlet.Filter;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.shiro.cache.ehcache.EhCacheManager;
|
||||
import org.apache.shiro.codec.Base64;
|
||||
import org.apache.shiro.config.ConfigurationException;
|
||||
import org.apache.shiro.io.ResourceUtils;
|
||||
import org.apache.shiro.mgt.SecurityManager;
|
||||
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
|
||||
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
|
||||
import org.apache.shiro.web.mgt.CookieRememberMeManager;
|
||||
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
|
||||
import org.apache.shiro.web.servlet.SimpleCookie;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||
import com.ruoyi.framework.shiro.LoginType;
|
||||
import com.ruoyi.framework.shiro.MyModularRealmAuthenticator;
|
||||
import com.ruoyi.framework.shiro.realm.AuthorizationRealm;
|
||||
import com.ruoyi.framework.shiro.realm.UserPhoneRealm;
|
||||
import com.ruoyi.framework.shiro.realm.UserRealm;
|
||||
import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
|
||||
import com.ruoyi.framework.shiro.session.OnlineSessionFactory;
|
||||
|
|
@ -32,7 +16,33 @@ import com.ruoyi.framework.shiro.web.filter.online.OnlineSessionFilter;
|
|||
import com.ruoyi.framework.shiro.web.filter.sync.SyncOnlineSessionFilter;
|
||||
import com.ruoyi.framework.shiro.web.session.OnlineWebSessionManager;
|
||||
import com.ruoyi.framework.shiro.web.session.SpringSessionValidationScheduler;
|
||||
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
|
||||
import org.apache.shiro.cache.ehcache.EhCacheManager;
|
||||
import org.apache.shiro.codec.Base64;
|
||||
import org.apache.shiro.config.ConfigurationException;
|
||||
import org.apache.shiro.io.ResourceUtils;
|
||||
import org.apache.shiro.mgt.SecurityManager;
|
||||
import org.apache.shiro.realm.AuthorizingRealm;
|
||||
import org.apache.shiro.realm.Realm;
|
||||
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
|
||||
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
|
||||
import org.apache.shiro.web.mgt.CookieRememberMeManager;
|
||||
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
|
||||
import org.apache.shiro.web.servlet.SimpleCookie;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 权限配置加载
|
||||
|
|
@ -40,8 +50,7 @@ import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
|
|||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
public class ShiroConfig
|
||||
{
|
||||
public class ShiroConfig {
|
||||
public static final String PREMISSION_STRING = "perms[\"{0}\"]";
|
||||
|
||||
// Session超时时间,单位为毫秒(默认30分钟)
|
||||
|
|
@ -84,17 +93,13 @@ public class ShiroConfig
|
|||
* 缓存管理器 使用Ehcache实现
|
||||
*/
|
||||
@Bean
|
||||
public EhCacheManager getEhCacheManager()
|
||||
{
|
||||
public EhCacheManager getEhCacheManager() {
|
||||
net.sf.ehcache.CacheManager cacheManager = net.sf.ehcache.CacheManager.getCacheManager("ruoyi");
|
||||
EhCacheManager em = new EhCacheManager();
|
||||
if (StringUtils.isNull(cacheManager))
|
||||
{
|
||||
if (StringUtils.isNull(cacheManager)) {
|
||||
em.setCacheManager(new net.sf.ehcache.CacheManager(getCacheManagerConfigFileInputStream()));
|
||||
return em;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
em.setCacheManager(cacheManager);
|
||||
return em;
|
||||
}
|
||||
|
|
@ -103,24 +108,18 @@ public class ShiroConfig
|
|||
/**
|
||||
* 返回配置文件流 避免ehcache配置文件一直被占用,无法完全销毁项目重新部署
|
||||
*/
|
||||
protected InputStream getCacheManagerConfigFileInputStream()
|
||||
{
|
||||
protected InputStream getCacheManagerConfigFileInputStream() {
|
||||
String configFile = "classpath:ehcache/ehcache-shiro.xml";
|
||||
InputStream inputStream = null;
|
||||
try
|
||||
{
|
||||
try {
|
||||
inputStream = ResourceUtils.getInputStreamForPath(configFile);
|
||||
byte[] b = IOUtils.toByteArray(inputStream);
|
||||
InputStream in = new ByteArrayInputStream(b);
|
||||
return in;
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
} catch (IOException e) {
|
||||
throw new ConfigurationException(
|
||||
"Unable to obtain input stream for cacheManagerConfigFile [" + configFile + "]", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
} finally {
|
||||
IOUtils.closeQuietly(inputStream);
|
||||
}
|
||||
}
|
||||
|
|
@ -129,8 +128,7 @@ public class ShiroConfig
|
|||
* 自定义Realm
|
||||
*/
|
||||
@Bean
|
||||
public UserRealm userRealm(EhCacheManager cacheManager)
|
||||
{
|
||||
public UserRealm userRealm(EhCacheManager cacheManager) {
|
||||
UserRealm userRealm = new UserRealm();
|
||||
userRealm.setCacheManager(cacheManager);
|
||||
return userRealm;
|
||||
|
|
@ -140,8 +138,7 @@ public class ShiroConfig
|
|||
* 自定义sessionDAO会话
|
||||
*/
|
||||
@Bean
|
||||
public OnlineSessionDAO sessionDAO()
|
||||
{
|
||||
public OnlineSessionDAO sessionDAO() {
|
||||
OnlineSessionDAO sessionDAO = new OnlineSessionDAO();
|
||||
return sessionDAO;
|
||||
}
|
||||
|
|
@ -150,8 +147,7 @@ public class ShiroConfig
|
|||
* 自定义sessionFactory会话
|
||||
*/
|
||||
@Bean
|
||||
public OnlineSessionFactory sessionFactory()
|
||||
{
|
||||
public OnlineSessionFactory sessionFactory() {
|
||||
OnlineSessionFactory sessionFactory = new OnlineSessionFactory();
|
||||
return sessionFactory;
|
||||
}
|
||||
|
|
@ -160,8 +156,7 @@ public class ShiroConfig
|
|||
* 会话管理器
|
||||
*/
|
||||
@Bean
|
||||
public OnlineWebSessionManager sessionManager()
|
||||
{
|
||||
public OnlineWebSessionManager sessionManager() {
|
||||
OnlineWebSessionManager manager = new OnlineWebSessionManager();
|
||||
// 加入缓存管理器
|
||||
manager.setCacheManager(getEhCacheManager());
|
||||
|
|
@ -186,11 +181,22 @@ public class ShiroConfig
|
|||
* 安全管理器
|
||||
*/
|
||||
@Bean
|
||||
public SecurityManager securityManager(UserRealm userRealm, SpringSessionValidationScheduler springSessionValidationScheduler)
|
||||
{
|
||||
public SecurityManager securityManager(UserRealm userRealm, SpringSessionValidationScheduler springSessionValidationScheduler) {
|
||||
|
||||
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
|
||||
// 设置realm.
|
||||
securityManager.setRealm(userRealm);
|
||||
// securityManager.setRealm(userRealm);
|
||||
// 修改为多realm
|
||||
securityManager.setAuthenticator(modularRealmAuthenticator());
|
||||
List<Realm> realms = new ArrayList<>();
|
||||
// 统一角色权限控制realm
|
||||
realms.add(authorizingRealm());
|
||||
// 用户密码登录realm
|
||||
realms.add(userRealm());
|
||||
// 短信登录
|
||||
realms.add(userPhoneRealm());
|
||||
securityManager.setRealms(realms);
|
||||
|
||||
// 记住我
|
||||
securityManager.setRememberMeManager(rememberMeManager());
|
||||
// 注入缓存管理器;
|
||||
|
|
@ -203,8 +209,7 @@ public class ShiroConfig
|
|||
/**
|
||||
* 退出过滤器
|
||||
*/
|
||||
public LogoutFilter logoutFilter()
|
||||
{
|
||||
public LogoutFilter logoutFilter() {
|
||||
LogoutFilter logoutFilter = new LogoutFilter();
|
||||
logoutFilter.setLoginUrl(loginUrl);
|
||||
return logoutFilter;
|
||||
|
|
@ -214,8 +219,7 @@ public class ShiroConfig
|
|||
* Shiro过滤器配置
|
||||
*/
|
||||
@Bean
|
||||
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager)
|
||||
{
|
||||
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
|
||||
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
|
||||
// Shiro的核心安全接口,这个属性是必须的
|
||||
shiroFilterFactoryBean.setSecurityManager(securityManager);
|
||||
|
|
@ -241,6 +245,8 @@ public class ShiroConfig
|
|||
filterChainDefinitionMap.put("/logout", "logout");
|
||||
// 不需要拦截的访问
|
||||
filterChainDefinitionMap.put("/login", "anon,captchaValidate");
|
||||
// 不需要拦截的访问
|
||||
filterChainDefinitionMap.put("/phoneLogin", "anon,captchaValidate");
|
||||
// 系统权限列表
|
||||
// filterChainDefinitionMap.putAll(SpringUtils.getBean(IMenuService.class).selectPermsAll());
|
||||
|
||||
|
|
@ -263,8 +269,7 @@ public class ShiroConfig
|
|||
* 自定义在线用户处理过滤器
|
||||
*/
|
||||
@Bean
|
||||
public OnlineSessionFilter onlineSessionFilter()
|
||||
{
|
||||
public OnlineSessionFilter onlineSessionFilter() {
|
||||
OnlineSessionFilter onlineSessionFilter = new OnlineSessionFilter();
|
||||
onlineSessionFilter.setLoginUrl(loginUrl);
|
||||
return onlineSessionFilter;
|
||||
|
|
@ -274,8 +279,7 @@ public class ShiroConfig
|
|||
* 自定义在线用户同步过滤器
|
||||
*/
|
||||
@Bean
|
||||
public SyncOnlineSessionFilter syncOnlineSessionFilter()
|
||||
{
|
||||
public SyncOnlineSessionFilter syncOnlineSessionFilter() {
|
||||
SyncOnlineSessionFilter syncOnlineSessionFilter = new SyncOnlineSessionFilter();
|
||||
return syncOnlineSessionFilter;
|
||||
}
|
||||
|
|
@ -284,8 +288,7 @@ public class ShiroConfig
|
|||
* 自定义验证码过滤器
|
||||
*/
|
||||
@Bean
|
||||
public CaptchaValidateFilter captchaValidateFilter()
|
||||
{
|
||||
public CaptchaValidateFilter captchaValidateFilter() {
|
||||
CaptchaValidateFilter captchaValidateFilter = new CaptchaValidateFilter();
|
||||
captchaValidateFilter.setCaptchaEnabled(captchaEnabled);
|
||||
captchaValidateFilter.setCaptchaType(captchaType);
|
||||
|
|
@ -295,8 +298,7 @@ public class ShiroConfig
|
|||
/**
|
||||
* cookie 属性设置
|
||||
*/
|
||||
public SimpleCookie rememberMeCookie()
|
||||
{
|
||||
public SimpleCookie rememberMeCookie() {
|
||||
SimpleCookie cookie = new SimpleCookie("rememberMe");
|
||||
cookie.setDomain(domain);
|
||||
cookie.setPath(path);
|
||||
|
|
@ -308,8 +310,7 @@ public class ShiroConfig
|
|||
/**
|
||||
* 记住我
|
||||
*/
|
||||
public CookieRememberMeManager rememberMeManager()
|
||||
{
|
||||
public CookieRememberMeManager rememberMeManager() {
|
||||
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
|
||||
cookieRememberMeManager.setCookie(rememberMeCookie());
|
||||
cookieRememberMeManager.setCipherKey(Base64.decode("fCq+/xW488hMTCD+cmJ3aQ=="));
|
||||
|
|
@ -320,8 +321,7 @@ public class ShiroConfig
|
|||
* thymeleaf模板引擎和shiro框架的整合
|
||||
*/
|
||||
@Bean
|
||||
public ShiroDialect shiroDialect()
|
||||
{
|
||||
public ShiroDialect shiroDialect() {
|
||||
return new ShiroDialect();
|
||||
}
|
||||
|
||||
|
|
@ -330,10 +330,57 @@ public class ShiroConfig
|
|||
*/
|
||||
@Bean
|
||||
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
|
||||
@Qualifier("securityManager") SecurityManager securityManager)
|
||||
{
|
||||
@Qualifier("securityManager") SecurityManager securityManager) {
|
||||
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
|
||||
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
|
||||
return authorizationAttributeSourceAdvisor;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义的Realm管理,主要针对多realm
|
||||
*/
|
||||
@Bean("myModularRealmAuthenticator")
|
||||
public MyModularRealmAuthenticator modularRealmAuthenticator() {
|
||||
MyModularRealmAuthenticator customizedModularRealmAuthenticator = new MyModularRealmAuthenticator();
|
||||
// 设置realm判断条件
|
||||
customizedModularRealmAuthenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
|
||||
|
||||
return customizedModularRealmAuthenticator;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthorizingRealm authorizingRealm() {
|
||||
AuthorizationRealm authorizationRealm = new AuthorizationRealm();
|
||||
authorizationRealm.setName(LoginType.COMMON.getType());
|
||||
|
||||
return authorizationRealm;
|
||||
}
|
||||
|
||||
/**
|
||||
* 账号密码登录realm
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public UserRealm userRealm() {
|
||||
UserRealm userRealm = new UserRealm();
|
||||
userRealm.setName(LoginType.USER_PASSWORD.getType());
|
||||
|
||||
return userRealm;
|
||||
}
|
||||
|
||||
/**
|
||||
* 手机号验证码登录realm
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public UserPhoneRealm userPhoneRealm() {
|
||||
UserPhoneRealm userPhoneRealm = new UserPhoneRealm();
|
||||
userPhoneRealm.setName(LoginType.USER_PHONE.getType());
|
||||
|
||||
return userPhoneRealm;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
package com.ruoyi.framework.shiro;
|
||||
|
||||
/**
|
||||
* @Description 登录方式的枚举类,存放我们所有的登录方式
|
||||
* https://blog.csdn.net/zhourenfei17/article/details/88826911
|
||||
* @Author 胡浩
|
||||
* @Date 2019/6/3
|
||||
**/
|
||||
public enum LoginType {
|
||||
/** 通用 **/
|
||||
COMMON("common_realm"),
|
||||
/** 用户密码登录 **/
|
||||
USER_PASSWORD("user_password_realm"),
|
||||
/** 手机验证码登录 **/
|
||||
USER_PHONE("user_phone_realm"),
|
||||
/** 二维码登录 **/
|
||||
QRCODE_LOGIN("qrcode_login_realm"),
|
||||
/** 第三方登录(微信登录) **/
|
||||
WECHAT_LOGIN("wechat_login_realm");
|
||||
|
||||
private String type;
|
||||
|
||||
private LoginType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.type.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package com.ruoyi.framework.shiro;
|
||||
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.apache.shiro.authc.AuthenticationInfo;
|
||||
import org.apache.shiro.authc.AuthenticationToken;
|
||||
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
|
||||
import org.apache.shiro.realm.Realm;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* @Description
|
||||
* 创建自定义的多relam的管理策略
|
||||
* @Author 胡浩
|
||||
* @Date 2019/6/3
|
||||
**/
|
||||
public class MyModularRealmAuthenticator extends ModularRealmAuthenticator {
|
||||
@Override
|
||||
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
|
||||
// 判断getRealms()是否返回为空
|
||||
assertRealmsConfigured();
|
||||
|
||||
// 所有Realm
|
||||
Collection<Realm> realms = getRealms();
|
||||
// 登录类型对应的所有Realm
|
||||
HashMap<String, Realm> realmHashMap = new HashMap<>(realms.size());
|
||||
for (Realm realm : realms) {
|
||||
realmHashMap.put(realm.getName(), realm);
|
||||
}
|
||||
|
||||
UserToken token = (UserToken) authenticationToken;
|
||||
// 登录类型
|
||||
LoginType loginType = token.getLoginType();
|
||||
|
||||
if (realmHashMap.get(loginType.getType()) != null) {
|
||||
return doSingleRealmAuthentication(realmHashMap.get(loginType.getType()), token);
|
||||
} else {
|
||||
return doMultiRealmAuthentication(realms, token);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
package com.ruoyi.framework.shiro;
|
||||
|
||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||
|
||||
/**
|
||||
* @Description
|
||||
* @Author 胡浩
|
||||
* @Date 2019/6/3
|
||||
**/
|
||||
public class UserToken extends UsernamePasswordToken {
|
||||
/**
|
||||
* 登录方式
|
||||
**/
|
||||
private LoginType loginType;
|
||||
/**
|
||||
* 微信code
|
||||
**/
|
||||
private String code;
|
||||
|
||||
public UserToken(final String username, final String password, LoginType loginType) {
|
||||
super(username, password);
|
||||
this.loginType = loginType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 记住我
|
||||
**/
|
||||
public UserToken(String username, String password, boolean rememberMe, LoginType loginType) {
|
||||
super(username, password, rememberMe);
|
||||
this.loginType = loginType;
|
||||
}
|
||||
|
||||
// TODO 由于是demo方法,此处微信只传一个code参数,其他参数根据实际情况添加
|
||||
public UserToken(String username, String password, String code, LoginType loginType) {
|
||||
super(username, password);
|
||||
this.loginType = loginType;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public LoginType getLoginType() {
|
||||
return loginType;
|
||||
}
|
||||
|
||||
public void setLoginType(LoginType loginType) {
|
||||
this.loginType = loginType;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
package com.ruoyi.framework.shiro.realm;
|
||||
|
||||
import com.ruoyi.framework.util.ShiroUtils;
|
||||
import com.ruoyi.system.domain.SysUser;
|
||||
import com.ruoyi.system.service.ISysMenuService;
|
||||
import com.ruoyi.system.service.ISysRoleService;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.apache.shiro.authc.AuthenticationInfo;
|
||||
import org.apache.shiro.authc.AuthenticationToken;
|
||||
import org.apache.shiro.authz.AuthorizationInfo;
|
||||
import org.apache.shiro.authz.SimpleAuthorizationInfo;
|
||||
import org.apache.shiro.realm.AuthorizingRealm;
|
||||
import org.apache.shiro.subject.PrincipalCollection;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @Description 统一角色授权管理realm
|
||||
* 当我们往shiro的SecurityManager中注入多个realm后,当一个新用户调用需授权的方法时,
|
||||
* 会依次调用所有的realm的doGetAuthoriztionInfo方法,
|
||||
* 而不是根据登录类型来调用不同realm的授权方法;因此为了避免重复代码(或者说重复授权),我们这边做统一处理。
|
||||
* @Author 胡浩
|
||||
* @Date 2019/6/4
|
||||
**/
|
||||
public class AuthorizationRealm extends AuthorizingRealm {
|
||||
@Autowired
|
||||
private ISysMenuService menuService;
|
||||
|
||||
@Autowired
|
||||
private ISysRoleService roleService;
|
||||
|
||||
/**
|
||||
* 授权
|
||||
*/
|
||||
@Override
|
||||
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
|
||||
SysUser user = ShiroUtils.getSysUser();
|
||||
// 角色列表
|
||||
Set<String> roles = new HashSet<String>();
|
||||
// 功能列表
|
||||
Set<String> menus = new HashSet<String>();
|
||||
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
|
||||
// 管理员拥有所有权限
|
||||
if (user.isAdmin()) {
|
||||
info.addRole("admin");
|
||||
info.addStringPermission("*:*:*");
|
||||
} else {
|
||||
roles = roleService.selectRoleKeys(user.getUserId());
|
||||
menus = menuService.selectPermsByUserId(user.getUserId());
|
||||
// 角色加入AuthorizationInfo认证对象
|
||||
info.setRoles(roles);
|
||||
// 权限加入AuthorizationInfo认证对象
|
||||
info.setStringPermissions(menus);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理缓存权限
|
||||
*/
|
||||
public void clearCachedAuthorizationInfo() {
|
||||
this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
|
||||
}
|
||||
|
||||
/**
|
||||
* 认证信息.(身份验证) : Authentication 是用来验证用户身份
|
||||
*/
|
||||
@Override
|
||||
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
package com.ruoyi.framework.shiro.realm;
|
||||
|
||||
import com.ruoyi.common.exception.user.*;
|
||||
import com.ruoyi.framework.shiro.LoginType;
|
||||
import com.ruoyi.framework.shiro.UserToken;
|
||||
import com.ruoyi.framework.shiro.service.SysLoginService;
|
||||
import com.ruoyi.system.domain.SysUser;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* @Description
|
||||
* @Author 胡浩
|
||||
* @Date 2019/6/4
|
||||
**/
|
||||
public class UserPhoneRealm extends AuthorizingRealm {
|
||||
private static final Logger log = LoggerFactory.getLogger(UserPhoneRealm.class);
|
||||
|
||||
|
||||
@Autowired
|
||||
private SysLoginService loginService;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return LoginType.USER_PHONE.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(AuthenticationToken token) {
|
||||
if (token instanceof UserToken) {
|
||||
return ((UserToken) token).getLoginType() == LoginType.USER_PHONE;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 授权
|
||||
*/
|
||||
@Override
|
||||
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录认证
|
||||
*/
|
||||
@Override
|
||||
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
|
||||
UserToken upToken = (UserToken) token;
|
||||
// UsernamePasswordToken upToken = (UsernamePasswordToken) token;
|
||||
String phone = upToken.getUsername();
|
||||
String validCode = "";
|
||||
if (upToken.getPassword() != null) {
|
||||
validCode = new String(upToken.getPassword());
|
||||
}
|
||||
|
||||
SysUser user = null;
|
||||
try {
|
||||
user = loginService.phoneLogin(phone, validCode);
|
||||
} catch (CaptchaException e) {
|
||||
throw new AuthenticationException(e.getMessage(), e);
|
||||
} catch (UserNotExistsException e) {
|
||||
throw new UnknownAccountException(e.getMessage(), e);
|
||||
} catch (UserPasswordNotMatchException e) {
|
||||
throw new IncorrectCredentialsException(e.getMessage(), e);
|
||||
} catch (UserPasswordRetryLimitExceedException e) {
|
||||
throw new ExcessiveAttemptsException(e.getMessage(), e);
|
||||
} catch (UserBlockedException e) {
|
||||
throw new LockedAccountException(e.getMessage(), e);
|
||||
} catch (RoleBlockedException e) {
|
||||
throw new LockedAccountException(e.getMessage(), e);
|
||||
} catch (Exception e) {
|
||||
log.info("对用户[" + phone + "]进行登录验证..验证未通过{}", e.getMessage());
|
||||
throw new AuthenticationException(e.getMessage(), e);
|
||||
}
|
||||
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, validCode, getName());
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理缓存权限
|
||||
*/
|
||||
public void clearCachedAuthorizationInfo() {
|
||||
this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,44 +1,27 @@
|
|||
package com.ruoyi.framework.shiro.realm;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import com.ruoyi.common.exception.user.*;
|
||||
import com.ruoyi.framework.shiro.LoginType;
|
||||
import com.ruoyi.framework.shiro.UserToken;
|
||||
import com.ruoyi.framework.shiro.service.SysLoginService;
|
||||
import com.ruoyi.system.domain.SysUser;
|
||||
import com.ruoyi.system.service.ISysMenuService;
|
||||
import com.ruoyi.system.service.ISysRoleService;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.apache.shiro.authc.AuthenticationInfo;
|
||||
import org.apache.shiro.authc.AuthenticationToken;
|
||||
import org.apache.shiro.authc.ExcessiveAttemptsException;
|
||||
import org.apache.shiro.authc.IncorrectCredentialsException;
|
||||
import org.apache.shiro.authc.LockedAccountException;
|
||||
import org.apache.shiro.authc.SimpleAuthenticationInfo;
|
||||
import org.apache.shiro.authc.UnknownAccountException;
|
||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||
import org.apache.shiro.authc.*;
|
||||
import org.apache.shiro.authz.AuthorizationInfo;
|
||||
import org.apache.shiro.authz.SimpleAuthorizationInfo;
|
||||
import org.apache.shiro.realm.AuthorizingRealm;
|
||||
import org.apache.shiro.subject.PrincipalCollection;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.ruoyi.common.exception.user.CaptchaException;
|
||||
import com.ruoyi.common.exception.user.RoleBlockedException;
|
||||
import com.ruoyi.common.exception.user.UserBlockedException;
|
||||
import com.ruoyi.common.exception.user.UserNotExistsException;
|
||||
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
|
||||
import com.ruoyi.common.exception.user.UserPasswordRetryLimitExceedException;
|
||||
import com.ruoyi.framework.shiro.service.SysLoginService;
|
||||
import com.ruoyi.framework.util.ShiroUtils;
|
||||
import com.ruoyi.system.domain.SysUser;
|
||||
import com.ruoyi.system.service.ISysMenuService;
|
||||
import com.ruoyi.system.service.ISysRoleService;
|
||||
|
||||
/**
|
||||
* 自定义Realm 处理登录 权限
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class UserRealm extends AuthorizingRealm
|
||||
{
|
||||
public class UserRealm extends AuthorizingRealm {
|
||||
private static final Logger log = LoggerFactory.getLogger(UserRealm.class);
|
||||
|
||||
@Autowired
|
||||
|
|
@ -50,81 +33,75 @@ public class UserRealm extends AuthorizingRealm
|
|||
@Autowired
|
||||
private SysLoginService loginService;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return LoginType.USER_PASSWORD.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(AuthenticationToken token) {
|
||||
if (token instanceof UserToken) {
|
||||
return ((UserToken) token).getLoginType() == LoginType.USER_PASSWORD;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 授权
|
||||
*/
|
||||
@Override
|
||||
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0)
|
||||
{
|
||||
SysUser user = ShiroUtils.getSysUser();
|
||||
// 角色列表
|
||||
Set<String> roles = new HashSet<String>();
|
||||
// 功能列表
|
||||
Set<String> menus = new HashSet<String>();
|
||||
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
|
||||
// 管理员拥有所有权限
|
||||
if (user.isAdmin())
|
||||
{
|
||||
info.addRole("admin");
|
||||
info.addStringPermission("*:*:*");
|
||||
}
|
||||
else
|
||||
{
|
||||
roles = roleService.selectRoleKeys(user.getUserId());
|
||||
menus = menuService.selectPermsByUserId(user.getUserId());
|
||||
// 角色加入AuthorizationInfo认证对象
|
||||
info.setRoles(roles);
|
||||
// 权限加入AuthorizationInfo认证对象
|
||||
info.setStringPermissions(menus);
|
||||
}
|
||||
return info;
|
||||
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
|
||||
// SysUser user = ShiroUtils.getSysUser();
|
||||
// // 角色列表
|
||||
// Set<String> roles = new HashSet<String>();
|
||||
// // 功能列表
|
||||
// Set<String> menus = new HashSet<String>();
|
||||
// SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
|
||||
// // 管理员拥有所有权限
|
||||
// if (user.isAdmin()) {
|
||||
// info.addRole("admin");
|
||||
// info.addStringPermission("*:*:*");
|
||||
// } else {
|
||||
// roles = roleService.selectRoleKeys(user.getUserId());
|
||||
// menus = menuService.selectPermsByUserId(user.getUserId());
|
||||
// // 角色加入AuthorizationInfo认证对象
|
||||
// info.setRoles(roles);
|
||||
// // 权限加入AuthorizationInfo认证对象
|
||||
// info.setStringPermissions(menus);
|
||||
// }
|
||||
// return info;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录认证
|
||||
*/
|
||||
@Override
|
||||
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException
|
||||
{
|
||||
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
|
||||
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
|
||||
String username = upToken.getUsername();
|
||||
String password = "";
|
||||
if (upToken.getPassword() != null)
|
||||
{
|
||||
if (upToken.getPassword() != null) {
|
||||
password = new String(upToken.getPassword());
|
||||
}
|
||||
|
||||
SysUser user = null;
|
||||
try
|
||||
{
|
||||
try {
|
||||
user = loginService.login(username, password);
|
||||
}
|
||||
catch (CaptchaException e)
|
||||
{
|
||||
} catch (CaptchaException e) {
|
||||
throw new AuthenticationException(e.getMessage(), e);
|
||||
}
|
||||
catch (UserNotExistsException e)
|
||||
{
|
||||
} catch (UserNotExistsException e) {
|
||||
throw new UnknownAccountException(e.getMessage(), e);
|
||||
}
|
||||
catch (UserPasswordNotMatchException e)
|
||||
{
|
||||
} catch (UserPasswordNotMatchException e) {
|
||||
throw new IncorrectCredentialsException(e.getMessage(), e);
|
||||
}
|
||||
catch (UserPasswordRetryLimitExceedException e)
|
||||
{
|
||||
} catch (UserPasswordRetryLimitExceedException e) {
|
||||
throw new ExcessiveAttemptsException(e.getMessage(), e);
|
||||
}
|
||||
catch (UserBlockedException e)
|
||||
{
|
||||
} catch (UserBlockedException e) {
|
||||
throw new LockedAccountException(e.getMessage(), e);
|
||||
}
|
||||
catch (RoleBlockedException e)
|
||||
{
|
||||
} catch (RoleBlockedException e) {
|
||||
throw new LockedAccountException(e.getMessage(), e);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
} catch (Exception e) {
|
||||
log.info("对用户[" + username + "]进行登录验证..验证未通过{}", e.getMessage());
|
||||
throw new AuthenticationException(e.getMessage(), e);
|
||||
}
|
||||
|
|
@ -135,8 +112,7 @@ public class UserRealm extends AuthorizingRealm
|
|||
/**
|
||||
* 清理缓存权限
|
||||
*/
|
||||
public void clearCachedAuthorizationInfo()
|
||||
{
|
||||
public void clearCachedAuthorizationInfo() {
|
||||
this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@ import com.ruoyi.framework.util.ShiroUtils;
|
|||
import com.ruoyi.system.domain.SysUser;
|
||||
import com.ruoyi.system.service.ISysUserService;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 登录校验方法
|
||||
*
|
||||
|
|
@ -133,4 +136,60 @@ public class SysLoginService
|
|||
user.setLoginDate(DateUtils.getNowDate());
|
||||
userService.updateUserInfo(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* 手机验证码登录
|
||||
*/
|
||||
public SysUser phoneLogin(String phone, String validCode) {
|
||||
|
||||
//TODO 验证验证码
|
||||
// // 验证码校验
|
||||
// if (!StringUtils.isEmpty(ServletUtils.getRequest().getAttribute(ShiroConstants.CURRENT_CAPTCHA))) {
|
||||
// AsyncManager.me().execute(AsyncFactory.recordLogininfor(phone, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
|
||||
// throw new CaptchaException();
|
||||
// }
|
||||
|
||||
// 手机或验证码为空 错误
|
||||
if (StringUtils.isEmpty(phone) || StringUtils.isEmpty(validCode)) {
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(phone, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
|
||||
throw new UserNotExistsException();
|
||||
}
|
||||
|
||||
String regex = "^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(17[013678])|(18[0,5-9]))\\d{8}$";
|
||||
if (phone.length() != 11) {
|
||||
System.out.println("手机号应为11位数");
|
||||
} else {
|
||||
Pattern p = Pattern.compile(regex);
|
||||
Matcher m = p.matcher(phone);
|
||||
boolean isMatch = m.matches();
|
||||
if (isMatch) {
|
||||
System.out.println("您的手机号" + phone + "是正确格式@——@");
|
||||
} else {
|
||||
System.out.println("您的手机号" + phone + "是错误格式!!!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 查询用户信息
|
||||
SysUser user = userService.selectUserByPhoneNumber(phone);
|
||||
|
||||
if (user == null) {
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(phone, Constants.LOGIN_FAIL, MessageUtils.message("user.not.exists")));
|
||||
throw new UserNotExistsException();
|
||||
}
|
||||
|
||||
if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(phone, Constants.LOGIN_FAIL, MessageUtils.message("user.password.delete")));
|
||||
throw new UserDeleteException();
|
||||
}
|
||||
|
||||
if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(phone, Constants.LOGIN_FAIL, MessageUtils.message("user.blocked", user.getRemark())));
|
||||
throw new UserBlockedException();
|
||||
}
|
||||
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(phone, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
|
||||
recordLoginInfo(user);
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.ruoyi.framework.util;
|
||||
|
||||
import com.ruoyi.framework.shiro.realm.AuthorizationRealm;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
|
||||
import org.apache.shiro.mgt.RealmSecurityManager;
|
||||
|
|
@ -60,7 +61,8 @@ public class ShiroUtils
|
|||
public static void clearCachedAuthorizationInfo()
|
||||
{
|
||||
RealmSecurityManager rsm = (RealmSecurityManager) SecurityUtils.getSecurityManager();
|
||||
UserRealm realm = (UserRealm) rsm.getRealms().iterator().next();
|
||||
// UserRealm realm = (UserRealm) rsm.getRealms().iterator().next();
|
||||
AuthorizationRealm realm = (AuthorizationRealm) rsm.getRealms().iterator().next();
|
||||
realm.clearCachedAuthorizationInfo();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue