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("");
}
}