pom.xml
<!--shiro start-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
<!--shiro end-->
MyExceptionHandler 統一異常處理, json格式
@ControllerAdvice
@Slf4j
public class MyExceptionHandler {
// @ResponseBody
// @ExceptionHandler(BizException.class)
public ResData handleException(BizException e){
ResData resData = new ResData();
resData.setResInfo(false,e.getCode(), e.getMessage());
return resData;
}
@ResponseBody
@ExceptionHandler(Exception.class)
public ResData handleException(Exception e){
ResData resData = new ResData();
resData.setResInfo(false,RespCode.RespEnum.PARAMETER_IS_WRONG.getCode(), RespCode.RespEnum.PARAMETER_IS_WRONG.getDescribe());
return resData;
}
@ResponseBody
@ExceptionHandler(AccountException.class)
public ResData handlerUnauthorizedException(AccountException e) {
log.debug("MyExceptionHandler.handlerUnauthorizedException 權限認證Exception{}");
ResData resData = new ResData();
resData.setResInfo(false,RespCode.RespEnum.SYSERROR_PERMISSIONS_401.getCode(), RespCode.RespEnum.SYSERROR_PERMISSIONS_401.getDescribe());
return resData;
}
@ResponseBody
@ExceptionHandler(AuthorizationException.class)
public ResData handlerAuthorizationException(AuthorizationException e) {
log.debug("MyExceptionHandler.handlerAuthorizationException{}");
ResData resData = new ResData();
resData.setResInfo(false,RespCode.RespEnum.SYSERROR_PERMISSIONS_403.getCode(), RespCode.RespEnum.SYSERROR_PERMISSIONS_403.getDescribe());
return resData;
}
}
CustomManagerMvcConfig 可以來擴展SpringMVC的功能,此處主要處理跨域問題
package com.yxds.manager.common.interceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;
//使用 WebMvcConfigurerAdapter 可以來擴展SpringMVC的功能
//WebMvcConfigurationSupport 會是靜態資源失效需要擴展
//@EnableWebMvc 不要接管SpringMVC
@Configuration
public class CustomManagerMvcConfig implements WebMvcConfigurer {
//所有的WebMvcConfigurerAdapter組件都會一起起作用
@Bean //將組件註冊在容器
public WebMvcConfigurer webMvcConfigurer() {
WebMvcConfigurer adapter = new WebMvcConfigurer() {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//瀏覽器發送 /test 請求來到 success 添加視圖映射
registry.addViewController("/").setViewName("login");
registry.addViewController("/index.html").setViewName("login");
//防止重複提交
registry.addViewController("/home.html").setViewName("home");
// registry.addViewController("/welcome.html").setViewName("welcome");
}
//註冊攔截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
//super.addInterceptors(registry);
//靜態資源; *.css , *.js
//SpringBoot已經做好了靜態資源映射
//免登陸
if(false){
registry.addInterceptor(new ManagerLoginHandlerInterceptor())
// 排除配置
.excludePathPatterns("/",
"/error",
"/static/**",
//排除訪問swagger
"/swagger-resources/**", "/v2/**", "/swagger-ui.html/**",
"/webjars/**",
"/index.html",
"/test/**",//過濾自檢代碼
"/sys/login",
"/sys/login/userMenuList",//userMenu
"/sys/logout",//退出
"/sys/Promote/SumKey/*"//首頁數據
)
// 攔截配置
.addPathPatterns("/**");
}
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/");
registry.addResourceHandler("/templates/**")
.addResourceLocations("classpath:/templates/");
//過濾swagger
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
registry.addResourceHandler("/v2/api-docs/**")
.addResourceLocations("classpath:/META-INF/resources/v2/api-docs/");
//super.addResourceHandlers(registry);
}
@Override
public void addCorsMappings(CorsRegistry registry) {
WebMvcConfigurer.super.addCorsMappings(registry);
registry.addMapping("/**")//需要跨域訪問的Map路徑
.allowedOrigins("*")//允許跨域訪問的ip及端口
.allowedHeaders("*")//允許跨域訪問的Headers內容
.allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")//允許跨域訪問的方法,OPTIONS必須設置Shiro中用到
.allowCredentials(true);
}
};
return adapter;
}
// 以下WebMvcConfigurerAdapter 比較常用的重寫接口
// /** 解決跨域問題 **/
// public void addCorsMappings(CorsRegistry registry) ;
// /** 添加攔截器 **/
// void addInterceptors(InterceptorRegistry registry);
// /** 這裏配置視圖解析器 **/
// /** 視圖跳轉控制器 **/
// void addViewControllers(ViewControllerRegistry registry);
// void configureViewResolvers(ViewResolverRegistry registry);
// /** 配置內容裁決的一些選項 **/
// void configureContentNegotiation(ContentNegotiationConfigurer configurer);
// /** 視圖跳轉控制器 **/
// void addViewControllers(ViewControllerRegistry registry);
// /** 靜態資源處理 **/
// void addResourceHandlers(ResourceHandlerRegistry registry);
// /** 默認靜態資源處理器 **/
// void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer);
}
CORSAuthenticationFilter 自定義身份驗證過濾器
package com.yxds.manager.component.shiro;
import com.alibaba.fastjson.JSONObject;
import com.yxds.common.constants.Constants;
import com.yxds.common.constants.LocalSessionCache;
import com.yxds.common.exception.RespCode;
import com.yxds.common.protocol.respprotocol.ResData;
import com.yxds.common.utils.stringutil.StringUtil;
import com.yxds.dao.entity.sys.SysUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Slf4j
public class CORSAuthenticationFilter extends FormAuthenticationFilter {
public CORSAuthenticationFilter() {
super();
}
@Override
public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
//Always return true if the request's method is OPTIONS
if (request instanceof HttpServletRequest) {
if (((HttpServletRequest) request).getMethod().toUpperCase().equals("OPTIONS")) {
return true;
}
}
return super.isAccessAllowed(request, response, mappedValue);
}
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response)
throws Exception
{
// String token = WebUtils.toHttp(request).getHeader(Constants.SysConstants.SYS_USER_TOKEN);
if (isLoginRequest(request, response)) {
if (isLoginSubmission(request, response)) {
return executeLogin(request, response);
} else {
return true;
}
// }
// SysUser user =(SysUser) LocalSessionCache.getSession(token);
// if (StringUtil.isObjectNotEmpty(token)&&StringUtil.isObjectNotEmpty(user)&&token.trim().equals(user.getId().toString())) {
// if (isLoginSubmission(request, response)) {
// return executeLogin(request, response);
// } else {
// return true;
// }
}else {
//解決 WebUtils.toHttp 往返回response寫數據跨域問題
HttpServletRequest httpRequest = (HttpServletRequest) request;
String origin = httpRequest.getHeader("Origin");
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
httpServletResponse.setHeader("Access-Control-Allow-Origin", origin);
//通過對 Credentials 參數的設置,就可以保持跨域 Ajax 時的 Cookie
//設置了Allow-Credentials,Allow-Origin就不能爲*,需要指明具體的url域
httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
// 返回固定的JSON串
WebUtils.toHttp(response).setContentType("application/json; charset=utf-8");
ResData resData = new ResData();
resData.setResInfo(false, RespCode.RespEnum.SYSERROR_PERMISSIONS_401.getCode(), RespCode.RespEnum.SYSERROR_PERMISSIONS_401.getDescribe());
WebUtils.toHttp(response).getWriter().print(JSONObject.toJSONString(resData));
return false;
}
}
}
CustomSessionIdGenerator 自定義SessionId 生成器
package com.yxds.manager.component.shiro;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.SessionIdGenerator;
import java.io.Serializable;
import java.util.UUID;
public class CustomSessionIdGenerator implements SessionIdGenerator {
@Override
public Serializable generateId(Session session) {
return "yx"+ UUID.randomUUID().toString().replace("-","");
}
}
ShiroSessionManager 自定義Session 管理器
package com.yxds.manager.component.shiro;
import com.alibaba.fastjson.JSONObject;
import com.yxds.common.constants.Constants;
import com.yxds.common.constants.LocalSessionCache;
import com.yxds.common.exception.RespCode;
import com.yxds.common.protocol.respprotocol.ResData;
import com.yxds.common.utils.stringutil.StringUtil;
import com.yxds.service.shiro.ShiroUtilsManager;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
public class ShiroSessionManager extends DefaultWebSessionManager {
private Logger logger = LoggerFactory.getLogger(this.getClass());
// private static final String AUTHORIZATION = "Authorization";
private static final String AUTHORIZATION = Constants.SysConstants.SYS_USER_TOKEN;
private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request";
public ShiroSessionManager() {
super();
}
@Override
protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
//前端ajax的headers中必須傳入Authorization的值
String id = WebUtils.toHttp(request).getHeader(AUTHORIZATION);
Object sessionId = LocalSessionCache.getSession(id);
if(StringUtil.isObjectNotEmpty(id)){
Object o = LocalSessionCache.getSession(id+sessionId);
if(StringUtil.isObjectEmpty(o))
return null;
}
//如果請求頭中有 Authorization 則其值爲sessionId
if (!StringUtils.isEmpty(id)&& StringUtil.isObjectNotEmpty(sessionId)) {
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, REFERENCED_SESSION_ID_SOURCE);
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, sessionId.toString());
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
logger.info("調用MySessionManager獲取sessionId=" + id);
return sessionId.toString();
} else {
//否則按默認規則從cookie取sessionId
logger.info("調用MySessionManager使用默認模式從cookie獲取sessionID爲" + id);
return super.getSessionId(request, response);
}
}
}
UserShiroRealm 實現Realm
package com.yxds.manager.component.shiro;
import com.yxds.common.constants.Constants;
import com.yxds.dao.entity.sys.SysMenuButton;
import com.yxds.dao.entity.sys.SysUser;
import com.yxds.service.manager.sys.SysMenuButtonService;
import com.yxds.service.manager.sys.SysRoleMenuService;
import com.yxds.service.manager.sys.SysUserService;
import com.yxds.service.shiro.ShiroUtilsManager;
import lombok.extern.slf4j.Slf4j;
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.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Arrays;
import java.util.List;
@Slf4j
public class UserShiroRealm extends AuthorizingRealm {
@Autowired
SysUserService sysUserService;
@Autowired
SysMenuButtonService sysMenuButtonService;
@Autowired
SysRoleMenuService sysRoleMenuService;
/**
* 身份認證
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
log.debug("UserShiroRealm.doGetAuthenticationInfo{}", Constants.SysConstants.SHOW_DEBUG_TAG);
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
String username = token.getUsername();
SysUser hasSysUser = sysUserService.findByUserInfo(username);
if (hasSysUser == null) {
return null;
}
String loginPwd = hasSysUser.getLoginPwd();
hasSysUser.setLoginPwd("");
// 若存在,將此用戶存放到登錄認證info中,無需自己做密碼對比,Shiro會爲我們進行密碼對比校驗
//此處沒有加鹽
//hasSysUser 認證成功的返回信息
SimpleAuthenticationInfo simpleAuthenticationInfo =
new SimpleAuthenticationInfo(hasSysUser, loginPwd,ByteSource.Util.bytes(hasSysUser.getLoginName()), getName());
return simpleAuthenticationInfo;
}
/**
* 權限認證
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
log.debug("UserShiroRealm.doGetAuthorizationInfo{}", "執行Shiro權限認證"+Constants.SysConstants.SHOW_DEBUG_TAG);
SysUser sysUser = (SysUser) principalCollection.getPrimaryPrincipal();
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
if(ShiroUtilsManager.authcOpen){
if (sysUser.getLoginName().equals(Constants.SysConstants.SYS_ADMIN_TYPE)) {
authorizationInfo.addStringPermission("*:*:*");
}else {
if (sysUser != null) {
// List<SysMenuButton> sysMenuButtonList = sysMenuButtonService.getUserSysMenuButtonList(sysUser.getId());
String butFlag = sysRoleMenuService.getUserSysMenuButtonFlag(sysUser.getId());
List<String> butFlagList = Arrays.asList(butFlag.split(","));
for (String f : butFlagList) {
authorizationInfo.addStringPermission(f);
}
}
}
}else{
authorizationInfo.addStringPermission("*:*:*");
}
return authorizationInfo;
}
}
ShiroConfiguration
package com.yxds.manager.component.shiro;
import com.yxds.common.constants.Constants;
import com.yxds.service.shiro.ShiroUtilsManager;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;
@Slf4j
@Configuration
public class ShiroConfiguration {
@Bean(name = "shiroFilterFactoryBean")
public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
log.debug("ShiroConfiguration.shiroFilterFactoryBean{}", Constants.SysConstants.SHOW_DEBUG_TAG);
Map<String, String> filterChainDefinitionManager = new LinkedHashMap<String, String>();
filterChainDefinitionManager.put("/error", "anon");
filterChainDefinitionManager.put("/static/**", "anon");
//排除訪問swagger
filterChainDefinitionManager.put( "/swagger-resources/**", "anon");
filterChainDefinitionManager.put( "/v2/**", "anon");
filterChainDefinitionManager.put( "/swagger-ui.html/**", "anon");
filterChainDefinitionManager.put("/webjars/**", "anon");
filterChainDefinitionManager.put("/index.html", "anon");
filterChainDefinitionManager.put("/login.html", "anon");
filterChainDefinitionManager.put("/sys/login", "anon");
filterChainDefinitionManager.put("/sys/login/userMenuList", "anon");//userMenu
filterChainDefinitionManager.put("/sys/logout", "anon");//退出
filterChainDefinitionManager.put("/sys/Promote/SumKey/*", "anon");//首頁數據
filterChainDefinitionManager.put("/**", "user");// authc user 其他資源全部攔截.
if(!ShiroUtilsManager.authcOpen)
filterChainDefinitionManager.put("/**", "anon");
// shiroFilterFactoryBean.setLoginUrl("/unauth");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionManager);
//自定義過濾器
Map<String, Filter> filterMap = new LinkedHashMap<>();
filterMap.put("user",new CORSAuthenticationFilter());
shiroFilterFactoryBean.setFilters(filterMap);
return shiroFilterFactoryBean;
}
@Bean
public DefaultWebSecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(userShiroRealm());
securityManager.setCacheManager(ehCacheManager());
securityManager.setSessionManager(sessionManager());
return securityManager;
}
@Bean
public UserShiroRealm userShiroRealm() {
UserShiroRealm userShiroRealm = new UserShiroRealm();
//緩存開關 setCachingEnabled 管理 setAuthenticationCachingEnabled,setAuthorizationCachingEnabled
userShiroRealm.setCachingEnabled(false);
//啓用身份驗證緩存,即緩存AuthenticationInfo信息,默認false
// userShiroRealm.setAuthenticationCachingEnabled(false);
//緩存AuthenticationInfo信息的緩存名稱 在ehcache-shiro.xml中有對應緩存的配置
userShiroRealm.setAuthenticationCacheName("authenticationCache");
//啓用授權緩存,即緩存AuthorizationInfo信息,默認false
// userShiroRealm.setAuthorizationCachingEnabled(false);
//緩存AuthorizationInfo信息的緩存名稱 在ehcache-shiro.xml中有對應緩存的配置
userShiroRealm.setAuthorizationCacheName("authorizationCache");
userShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
return userShiroRealm;
}
/**
* 憑證匹配器
* (由於我們的密碼校驗交給Shiro的SimpleAuthenticationInfo進行處理了
* 所以我們需要修改下doGetAuthenticationInfo中的代碼;
* )
* @return
*/
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher(){
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:這裏使用MD5算法;
hashedCredentialsMatcher.setHashIterations(2);//散列的次數,比如散列兩次,相當於 md5(md5(""));
return hashedCredentialsMatcher;
}
@Bean(name = "ehCacheManager")
@DependsOn("lifecycleBeanPostProcessor")
public EhCacheManager ehCacheManager(){
EhCacheManager ehCacheManager = new EhCacheManager();
ehCacheManager.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");
return ehCacheManager;
}
@Bean
public SessionManager sessionManager() {
ShiroSessionManager sessionManager = new ShiroSessionManager();
sessionManager.setSessionDAO(sessionDAO());
sessionManager.setCacheManager(ehCacheManager());
//全局會話超時時間(單位毫秒),默認30分鐘 暫時設置爲10秒鐘 用來測試
sessionManager.setGlobalSessionTimeout(1800000);
// sessionManager.setGlobalSessionTimeout(10000);
//是否開啓刪除無效的session對象 默認爲true
sessionManager.setDeleteInvalidSessions(true);
//是否開啓定時調度器進行檢測過期session 默認爲true
// sessionManager.setSessionValidationSchedulerEnabled(true);
//設置session失效的掃描時間, 清理用戶直接關閉瀏覽器造成的孤立會話 默認爲 1個小時
//設置該屬性 就不需要設置 ExecutorServiceSessionValidationScheduler 底層也是默認自動調用ExecutorServiceSessionValidationScheduler
//暫時設置爲 5秒 用來測試
sessionManager.setSessionValidationInterval(3600000);
// sessionManager.setSessionValidationInterval(5000);
//取消url 後面的 JSESSIONID
sessionManager.setSessionIdUrlRewritingEnabled(false);
return sessionManager;
}
@Bean
public SessionDAO sessionDAO() {
EnterpriseCacheSessionDAO enterpriseCacheSessionDAO = new EnterpriseCacheSessionDAO();
//使用ehCacheManager
enterpriseCacheSessionDAO.setCacheManager(ehCacheManager());
//設置session緩存的名字 默認爲 shiro-activeSessionCache
enterpriseCacheSessionDAO.setActiveSessionsCacheName("shiro-activeSessionCache");
//sessionId生成器
enterpriseCacheSessionDAO.setSessionIdGenerator(sessionIdGenerator());
return enterpriseCacheSessionDAO;
}
@Bean
public CustomSessionIdGenerator sessionIdGenerator() {
return new CustomSessionIdGenerator();
}
@Bean(name = "lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@Bean
@ConditionalOnMissingBean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
return defaultAdvisorAutoProxyCreator;
}
/**
* 開啓shiro aop註解支持.
* 使用代理方式;所以需要開啓代碼支持;
* @param securityManager
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
///附加功能///////////////////////////////
}
ehcache-shiro.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="es">
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
/>
<!-- 授權緩存 -->
<cache name="authorizationCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache>
<!-- 認證緩存 -->
<cache name="authenticationCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache>
<!-- session緩存 -->
<cache name="shiro-activeSessionCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache>
</ehcache>
ShiroUtilsManager 用戶數據通過shiro獲取,獲取前判斷用戶的有效性
package com.yxds.service.shiro;
import com.yxds.common.constants.Constants;
import com.yxds.common.constants.LocalSessionCache;
import com.yxds.common.exception.BizException;
import com.yxds.common.exception.RespCode;
import com.yxds.common.utils.stringutil.StringUtil;
import com.yxds.dao.entity.sys.SysUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.apache.shiro.web.util.WebUtils;
import javax.servlet.http.HttpServletRequest;
@Slf4j
public class ShiroUtilsManager {
public static String defaultPwd = "123456";
public static boolean authcOpen = true;
public static Subject getSubject() {
return SecurityUtils.getSubject();
}
public static Session getSession() {
return SecurityUtils.getSubject().getSession();
}
public static void logout() {
getSubject().logout();
}
public static void setSysUser(SysUser user) {
Subject subject = getSubject();
PrincipalCollection principalCollection = subject.getPrincipals();
String realmName = principalCollection.getRealmNames().iterator().next();
PrincipalCollection newPrincipalCollection = new SimplePrincipalCollection(user, realmName);
// 重新加載Principal
subject.runAs(newPrincipalCollection);
}
public static SysUser getSysUser() {
SysUser user = (SysUser) getSubject().getPrincipal();
return user;
}
// public static SysUser getSysUser(HttpServletRequest request) {
// SysUser sysUser = (SysUser) LocalSessionCache.getSession(getToken(request));
// if(StringUtil.isObjectNotEmpty(sysUser))
// return sysUser;
// return null;
// }
public static String getToken(HttpServletRequest request) {
String token = WebUtils.toHttp(request).getHeader(Constants.SysConstants.SYS_USER_TOKEN);
if(StringUtil.isObjectEmpty(token))
throw new BizException(RespCode.RespEnum.SYSERROR_PERMISSIONS_401.getCode(), RespCode.RespEnum.SYSERROR_PERMISSIONS_401.getDescribe());
return token;
}
public static String getIp() {
return getSubject().getSession().getHost();
}
public static String getSessionId() {
return String.valueOf(getSubject().getSession().getId());
}
public static Integer getUserId() {
Subject subject = getSubject();
if(subject.isAuthenticated()||subject.isRemembered()){
Long userId =getSysUser().getId().longValue();
return userId.intValue() ;
}else {
if(authcOpen){
throw new BizException(RespCode.RespEnum.SYSERROR_PERMISSIONS_401.getCode(), RespCode.RespEnum.SYSERROR_PERMISSIONS_401.getDescribe());
}
return null;
}
}
public static String getLoginName() {
return getSysUser().getLoginName();
}
/**
* 生成隨機鹽
*/
public static String randomSalt() {
// 一個Byte佔兩個字節,此處生成的3字節,字符串長度爲6
SecureRandomNumberGenerator secureRandom = new SecureRandomNumberGenerator();
String hex = secureRandom.nextBytes(3).toHex();
return hex;
}
public static String getPassword(String name , Object password , String userSalt){
String hashAlgorithmName = "MD5";
Object salt = ByteSource.Util.bytes(name+userSalt);
int hashIterations = 2;
Object result = new SimpleHash(hashAlgorithmName, password, salt, hashIterations);
return result.toString();
}
public static String getPassword(String name , Object password){
String hashAlgorithmName = "MD5";
Object salt = ByteSource.Util.bytes(name);
int hashIterations = 2;
Object result = new SimpleHash(hashAlgorithmName, password, salt, hashIterations);
return result.toString();
}
public static void main(String[] args) {
log.info("////////////////////////////////");
// String randomSalt=ShiroUtilsManager.randomSalt();
// log.info(randomSalt);
// log.info(ShiroUtilsManager.getPassword("test",ShiroUtilsManager.defaultPwd,randomSalt));
log.info(ShiroUtilsManager.getPassword("dbtest", ShiroUtilsManager.defaultPwd));
log.info("////////////////////////////////");
}
}