commit
This commit is contained in:
@@ -7,9 +7,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
public class Constants {
|
public class Constants {
|
||||||
|
|
||||||
/**
|
|
||||||
* 企业用户需要审核才能登陆,非企业用户默认审核成功
|
|
||||||
*/
|
|
||||||
public static String userStatus_0="0";//注册用户未审核
|
public static String userStatus_0="0";//注册用户未审核
|
||||||
public static String userStatus_1="1";//注册用户已审核
|
public static String userStatus_1="1";//注册用户已审核
|
||||||
public static String userStatus_2="2";//注册用户被锁定
|
public static String userStatus_2="2";//注册用户被锁定
|
||||||
@@ -31,65 +29,7 @@ public class Constants {
|
|||||||
*/
|
*/
|
||||||
public final static String REDIS_SHIRO_SESSION = "shiro-session:";
|
public final static String REDIS_SHIRO_SESSION = "shiro-session:";
|
||||||
/*****************************************shiro redis 管理设置 end*********************************************************/
|
/*****************************************shiro redis 管理设置 end*********************************************************/
|
||||||
|
|
||||||
|
|
||||||
/*****************************************报表导出 start*********************************************************/
|
|
||||||
|
|
||||||
public static List<String> list1 =new ArrayList<String>();
|
|
||||||
public static List<String> list2 =new ArrayList<String>();
|
|
||||||
public static Map<String, List> map=new HashMap<String, List>();
|
|
||||||
public static Map<String, String> mapValue=new HashMap<String, String>();
|
|
||||||
|
|
||||||
static{
|
|
||||||
|
|
||||||
list1.add("与工业控制系统网络相连的网络");
|
|
||||||
list1.add("连接方式");
|
|
||||||
list1.add("连接时间");
|
|
||||||
list1.add("连接后身份认证方式");
|
|
||||||
list1.add("连接管理制度");
|
|
||||||
list1.add("合法系统间互联的识别和认证技术措施");
|
|
||||||
|
|
||||||
|
|
||||||
list2.add("移动存储介质使用管理制度");
|
|
||||||
list2.add("系统网络和公共网之间交叉使用移动存储介质");
|
|
||||||
list2.add("工业控制系统主机的存储介质使用情况检查");
|
|
||||||
list2.add("移动存储介质自动播放功能");
|
|
||||||
list2.add("工业控制系统与其他系统之间专用的安全信息交换途径");
|
|
||||||
list2.add("移动存储介质销毁处置流程");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
map.put("工业控制系统网络与公共网络的连接管理",list1);
|
|
||||||
map.put("存储介质使用管理",list2);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
mapValue.put("与工业控制系统网络相连的网络", "内部局域网-互联网-企业管理网-其他网络-无连接");
|
|
||||||
mapValue.put("连接方式","直接相连-采取隔离措施后连接-防火墙");
|
|
||||||
mapValue.put("连接时间","始终连接-有需要时连接-无连接");
|
|
||||||
mapValue.put("连接后身份认证方式","口令-数字认证技术-无认证");
|
|
||||||
mapValue.put("连接管理制度","审批备案-定期检查-风险评估-隔离措施有效性验证-无");
|
|
||||||
mapValue.put("合法系统间互联的识别和认证技术措施","有-无");
|
|
||||||
|
|
||||||
mapValue.put("移动存储介质使用管理制度","有-无");
|
|
||||||
mapValue.put("系统网络和公共网之间交叉使用移动存储介质","禁止-未禁止-未要求");
|
|
||||||
mapValue.put("工业控制系统主机的存储介质使用情况检查","定期-不定期-不检查");
|
|
||||||
mapValue.put("移动存储介质自动播放功能","明文禁止-未禁止-未要求");
|
|
||||||
mapValue.put("工业控制系统与其他系统之间专用的安全信息交换途径","有-无");
|
|
||||||
mapValue.put("移动存储介质销毁处置流程","有-无");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************报表导出 end*********************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
<groupId>demo.xinwin</groupId>
|
<groupId>demo.xinwin</groupId>
|
||||||
<artifactId>demo-shiro-service</artifactId>
|
<artifactId>demo-shiro-service</artifactId>
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
|||||||
@@ -66,5 +66,13 @@ public class RedisConfig extends CachingConfigurerSupport {
|
|||||||
template.setKeySerializer(new StringRedisSerializer());
|
template.setKeySerializer(new StringRedisSerializer());
|
||||||
return template;
|
return template;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -32,7 +32,10 @@ import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
|||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shiro测试Controller
|
* Shiro测试Controller
|
||||||
@@ -521,6 +524,7 @@ public class UserController {
|
|||||||
// token.setRememberMe(true);
|
// token.setRememberMe(true);
|
||||||
// 获取当前的Subject
|
// 获取当前的Subject
|
||||||
Subject currentUser = SecurityUtils.getSubject();
|
Subject currentUser = SecurityUtils.getSubject();
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 在调用了login方法后,SecurityManager会收到AuthenticationToken,并将其发送给已配置的Realm执行必须的认证检查
|
// 在调用了login方法后,SecurityManager会收到AuthenticationToken,并将其发送给已配置的Realm执行必须的认证检查
|
||||||
@@ -528,6 +532,7 @@ public class UserController {
|
|||||||
// 所以这一步在调用login(token)方法时,它会走到MyRealm.doGetAuthenticationInfo()方法中,具体验证方式详见此方法
|
// 所以这一步在调用login(token)方法时,它会走到MyRealm.doGetAuthenticationInfo()方法中,具体验证方式详见此方法
|
||||||
logger.info("对用户[" + username + "]进行登录验证..验证开始");
|
logger.info("对用户[" + username + "]进行登录验证..验证开始");
|
||||||
currentUser.login(token);
|
currentUser.login(token);
|
||||||
|
|
||||||
logger.info("对用户[" + username + "]进行登录验证..验证通过");
|
logger.info("对用户[" + username + "]进行登录验证..验证通过");
|
||||||
|
|
||||||
//begin 添加记录日志功能
|
//begin 添加记录日志功能
|
||||||
@@ -602,24 +607,6 @@ public class UserController {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// public Cookie getCookie(String cName,HttpServletRequest request) throws
|
|
||||||
// Exception
|
|
||||||
// {
|
|
||||||
// Cookie cookie=null;
|
|
||||||
// Cookie[] cs=this.getRequest().getCookies();
|
|
||||||
// if(cs!=null)
|
|
||||||
// {
|
|
||||||
// for(Cookie c:cs)
|
|
||||||
// {
|
|
||||||
// String name=c.getName();
|
|
||||||
// if(cName.equals(name))
|
|
||||||
// {
|
|
||||||
// cookie=c;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return cookie;
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -19,8 +19,6 @@ public class JedisShiroSessionRepository implements ShiroSessionRepository {
|
|||||||
private static Logger logger = LoggerFactory.getLogger(JedisShiroSessionRepository.class);
|
private static Logger logger = LoggerFactory.getLogger(JedisShiroSessionRepository.class);
|
||||||
|
|
||||||
private RedisTemplate<String, Object> objectRedisTemplate;
|
private RedisTemplate<String, Object> objectRedisTemplate;
|
||||||
// @Autowired
|
|
||||||
// RedisTemplate<Object, Object> redisTemplate;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveSession(Session session) {
|
public void saveSession(Session session) {
|
||||||
|
|||||||
@@ -46,8 +46,7 @@ public class MyShiroRealm extends AuthorizingRealm{
|
|||||||
/**
|
/**
|
||||||
* 权限认证,为当前登录的Subject授予角色和权限
|
* 权限认证,为当前登录的Subject授予角色和权限
|
||||||
* @see:本例中该方法的调用时机为需授权资源被访问时
|
* @see:本例中该方法的调用时机为需授权资源被访问时
|
||||||
* @see :并且每次访问需授权资源时都会执行该方法中的逻辑,这表明本例中默认并未启用AuthorizationCache
|
* @see :如果连续访问同一个URL(比如刷新),该方法不会被重复调用,Shiro有一个时间间隔(系统提供三种cache:内存,ehcache ,redis,在ehcache-shiro.xml中配置),超过这个时间间隔再刷新页面,该方法会被执行
|
||||||
* @see :如果连续访问同一个URL(比如刷新),该方法不会被重复调用,Shiro有一个时间间隔(也就是cache时间,在ehcache-shiro.xml中配置),超过这个时间间隔再刷新页面,该方法会被执行
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
|
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
|
||||||
@@ -65,13 +64,13 @@ public class MyShiroRealm extends AuthorizingRealm{
|
|||||||
List<ShiroRole> roleList=user.getRoleList();
|
List<ShiroRole> roleList=user.getRoleList();
|
||||||
for (ShiroRole role : roleList) {
|
for (ShiroRole role : roleList) {
|
||||||
info.addStringPermissions(role.getPermissionsName());
|
info.addStringPermissions(role.getPermissionsName());
|
||||||
|
// 或者按下面这样添加
|
||||||
|
// 添加一个角色,不是配置意义上的添加,而是证明该用户拥有admin角色
|
||||||
|
// info.addRole(role.getRoleName());
|
||||||
|
//添加权限
|
||||||
|
// info.addStringPermission("admin:manage");
|
||||||
}
|
}
|
||||||
// 或者按下面这样添加
|
|
||||||
// 添加一个角色,不是配置意义上的添加,而是证明该用户拥有admin角色
|
|
||||||
// info.addRole("admin");
|
|
||||||
//添加权限
|
|
||||||
// info.addStringPermission("admin:manage");
|
|
||||||
logger.info("已为用户[mike]赋予了[admin]角色和[admin:manage]权限");
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
// 返回null的话,就会导致任何用户访问被拦截的请求时,都会自动跳转到unauthorizedUrl指定的地址
|
// 返回null的话,就会导致任何用户访问被拦截的请求时,都会自动跳转到unauthorizedUrl指定的地址
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
package com.xinwei.shiro;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.apache.shiro.cache.Cache;
|
||||||
|
import org.apache.shiro.cache.CacheException;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.util.SerializationUtils;
|
||||||
|
|
||||||
|
import com.xinwei.utils.Constants;
|
||||||
|
|
||||||
|
|
||||||
|
public class RedisCache<K, V> implements Cache<K, V> {
|
||||||
|
|
||||||
|
private long expireTime = 120;// 缓存的超时时间,单位为s
|
||||||
|
private String name;
|
||||||
|
private RedisTemplate<String, V> redisTemplate;// 通过构造方法注入该对象
|
||||||
|
// private RedisTemplate<K, V> redisTemplate;// 通过构造方法注入该对象
|
||||||
|
|
||||||
|
public RedisCache() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public RedisCache(long expireTime, RedisTemplate<String, V> redisTemplate,String name) {
|
||||||
|
super();
|
||||||
|
this.expireTime = expireTime;
|
||||||
|
this.redisTemplate = redisTemplate;
|
||||||
|
this.name=name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过key来获取对应的缓存对象
|
||||||
|
* 通过源码我们可以发现,shiro需要的key的类型为Object,V的类型为AuthorizationInfo对象
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public V get(K key) throws CacheException {
|
||||||
|
//return redisTemplate.opsForValue().get(key);
|
||||||
|
V obj =redisTemplate.opsForValue().get(name+new String(SerializationUtils.serialize(getCacheKey(key))));
|
||||||
|
if(obj!=null)
|
||||||
|
{
|
||||||
|
System.out.println(obj.toString());
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将权限信息加入缓存中
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public V put(K key, V value) throws CacheException {
|
||||||
|
|
||||||
|
// redisTemplate.opsForValue().set(key, value, this.expireTime, TimeUnit.SECONDS);
|
||||||
|
redisTemplate.opsForValue().set(name+new String(SerializationUtils.serialize(getCacheKey(key))), value, this.expireTime, TimeUnit.SECONDS);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将权限信息从缓存中删除
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public V remove(K key) throws CacheException {
|
||||||
|
// V v = redisTemplate.opsForValue().get(key);
|
||||||
|
// redisTemplate.opsForValue().getOperations().delete(key);
|
||||||
|
|
||||||
|
V v = redisTemplate.opsForValue().get(name+new String(SerializationUtils.serialize(getCacheKey(key))));
|
||||||
|
redisTemplate.opsForValue().getOperations().delete(name+new String(SerializationUtils.serialize(getCacheKey(key))));
|
||||||
|
|
||||||
|
System.out.println("====removeremove========="+key+"===============");
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() throws CacheException {
|
||||||
|
System.out.println("clearclearclearclearclearclearclearclearclear");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<K> keys() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<V> values() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getCacheKey(Object key) {
|
||||||
|
return Constants.REDIS_SHIRO_CACHE + ":" + key;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package com.xinwei.shiro;
|
||||||
|
|
||||||
|
import org.apache.shiro.cache.Cache;
|
||||||
|
import org.apache.shiro.cache.CacheException;
|
||||||
|
import org.apache.shiro.cache.CacheManager;
|
||||||
|
import org.apache.shiro.util.Destroyable;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
|
||||||
|
import com.xinwei.spring.boot.autoconfigure.shiro.ShiroProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @desc 该类提供redis cache。缓存 登录失败次数和用户权限。
|
||||||
|
* 过期时间分别对应application.yml 中的
|
||||||
|
* retry-expire-time-redis
|
||||||
|
* authorization-expire-time-redis
|
||||||
|
* @author wangxinwei
|
||||||
|
* @date 2018-02-07 04:23
|
||||||
|
*/
|
||||||
|
public class RedisCacheManager implements CacheManager, Destroyable {
|
||||||
|
|
||||||
|
|
||||||
|
private RedisTemplate redisTemplate;
|
||||||
|
private long expireTime;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ShiroProperties properties;
|
||||||
|
|
||||||
|
public RedisCacheManager(RedisTemplate redisTemplateTemp){
|
||||||
|
redisTemplate = redisTemplateTemp;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public <K, V> Cache<K, V> getCache(String name) throws CacheException {
|
||||||
|
|
||||||
|
if(name.equals("passwordRetryCache")){
|
||||||
|
expireTime = properties.getRetryExpireTimeRedis();
|
||||||
|
}else{
|
||||||
|
expireTime = properties.getAuthorizationExpireTimeRedis();
|
||||||
|
}
|
||||||
|
return new RedisCache<K, V>(expireTime, redisTemplate,name);// 为了简化代码的编写,此处直接new一个Cache
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() throws Exception {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,16 +1,31 @@
|
|||||||
package com.xinwei.shiro;
|
package com.xinwei.shiro;
|
||||||
|
|
||||||
|
import org.apache.shiro.cache.CacheManager;
|
||||||
|
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
|
||||||
|
import org.apache.shiro.cache.ehcache.EhCacheManager;
|
||||||
import org.apache.shiro.session.mgt.eis.SessionDAO;
|
import org.apache.shiro.session.mgt.eis.SessionDAO;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.DependsOn;
|
import org.springframework.context.annotation.DependsOn;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
|
||||||
|
import com.xinwei.spring.boot.autoconfigure.shiro.ShiroProperties;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public class ShiroConfiguration {
|
public class ShiroConfiguration {
|
||||||
|
@Autowired
|
||||||
|
public ShiroProperties properties;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
* 注释掉该方法时 ,shiro的登录会话session由ehcache保持。
|
* 注释掉该方法时 ,shiro的登录会话session由ehcache保持。
|
||||||
* 打开该方法时,shiro的登录回话session由redis保持。
|
* 打开该方法时,shiro的登录回话session由redis保持。
|
||||||
* @param jedisShiroSessionRepository
|
* @param jedisShiroSessionRepository
|
||||||
@@ -23,7 +38,9 @@ public class ShiroConfiguration {
|
|||||||
customShiroSessionDAO.setShiroSessionRepository(jedisShiroSessionRepository);
|
customShiroSessionDAO.setShiroSessionRepository(jedisShiroSessionRepository);
|
||||||
return customShiroSessionDAO;
|
return customShiroSessionDAO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@DependsOn(value = { "objectRedisTemplate" })
|
@DependsOn(value = { "objectRedisTemplate" })
|
||||||
public JedisShiroSessionRepository jedisShiroSessionRepository(RedisTemplate<String, Object> objectRedisTemplate) {
|
public JedisShiroSessionRepository jedisShiroSessionRepository(RedisTemplate<String, Object> objectRedisTemplate) {
|
||||||
@@ -33,5 +50,45 @@ public class ShiroConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (基于内存的)用户授权信息Cache
|
||||||
|
*/
|
||||||
|
@Bean(name = "shiroCacheManager")
|
||||||
|
@ConditionalOnMissingBean(name = "shiroCacheManager")
|
||||||
|
// @ConditionalOnMissingClass(value = {"org.apache.shiro.cache.ehcache.EhCacheManager"})
|
||||||
|
public CacheManager memoryCacheManager() {
|
||||||
|
|
||||||
|
return new MemoryConstrainedCacheManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (基于redis的)用户授权信息Cache
|
||||||
|
*/
|
||||||
|
@Bean(name = "shiroCacheManager")
|
||||||
|
@ConditionalOnMissingBean(name="shiroCacheManager")
|
||||||
|
public CacheManager redisCacheManager(RedisTemplate<String, Object> redisTemplate) {
|
||||||
|
|
||||||
|
return new RedisCacheManager(redisTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (基于ehcache的)用户授权信息Cache
|
||||||
|
*/
|
||||||
|
@Bean(name = "shiroCacheManager")
|
||||||
|
@ConditionalOnClass(name = {"org.apache.shiro.cache.ehcache.EhCacheManager"})
|
||||||
|
@ConditionalOnMissingBean(name = "shiroCacheManager")
|
||||||
|
public CacheManager ehcacheCacheManager() {
|
||||||
|
EhCacheManager ehCacheManager = new EhCacheManager();
|
||||||
|
ShiroProperties.Ehcache ehcache = properties.getEhcache();
|
||||||
|
if (ehcache.getCacheManagerConfigFile() != null) {
|
||||||
|
ehCacheManager.setCacheManagerConfigFile(ehcache.getCacheManagerConfigFile());
|
||||||
|
}
|
||||||
|
return ehCacheManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -3,12 +3,9 @@ shiro:
|
|||||||
custom-authc-filter-class: com.xinwei.shiro.AjaxAuthorizationFilter
|
custom-authc-filter-class: com.xinwei.shiro.AjaxAuthorizationFilter
|
||||||
login-url: /login
|
login-url: /login
|
||||||
success-url: /admin/sysFunctionManager/role_manager
|
success-url: /admin/sysFunctionManager/role_manager
|
||||||
unauthorized-url: /403
|
retry-max: 5
|
||||||
retry-max: 10000
|
retry-expire-time-redis: 5
|
||||||
sign-in:
|
authorization-expire-time-redis: 10
|
||||||
user-param: username
|
|
||||||
password-param: password
|
|
||||||
remember-me-param: rememberMe
|
|
||||||
hash-iterations: 1024
|
hash-iterations: 1024
|
||||||
hash-algorithm-name: MD5
|
hash-algorithm-name: MD5
|
||||||
stored-credentials-hex-encoded: false
|
stored-credentials-hex-encoded: false
|
||||||
@@ -18,6 +15,5 @@ shiro:
|
|||||||
validation-scheduler-enabled: true
|
validation-scheduler-enabled: true
|
||||||
filter-chain-definitions:
|
filter-chain-definitions:
|
||||||
/media/**: anon
|
/media/**: anon
|
||||||
/user/edit/*: authc,perms[user:edit]
|
|
||||||
/admin/**: authc
|
/admin/**: authc
|
||||||
|
|
||||||
|
|||||||
29
demo-shiro-web/src/main/resources/ehcache.xml
Executable file
29
demo-shiro-web/src/main/resources/ehcache.xml
Executable file
@@ -0,0 +1,29 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" updateCheck="false">
|
||||||
|
|
||||||
|
<!-- 权限认证缓存,20秒过期 -->
|
||||||
|
<defaultCache
|
||||||
|
maxElementsInMemory="10000"
|
||||||
|
eternal="false"
|
||||||
|
timeToIdleSeconds="20"
|
||||||
|
timeToLiveSeconds="0"
|
||||||
|
overflowToDisk="false"
|
||||||
|
diskPersistent="false"
|
||||||
|
diskExpiryThreadIntervalSeconds="120"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 登录次数缓存,超过N次锁定 锁定10秒钟 -->
|
||||||
|
<cache name="passwordRetryCache"
|
||||||
|
maxElementsInMemory="10000"
|
||||||
|
eternal="false"
|
||||||
|
timeToIdleSeconds="10"
|
||||||
|
timeToLiveSeconds="0"
|
||||||
|
overflowToDisk="false"
|
||||||
|
diskPersistent="false"
|
||||||
|
diskExpiryThreadIntervalSeconds="120">
|
||||||
|
</cache>
|
||||||
|
|
||||||
|
|
||||||
|
</ehcache>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
log4j.rootLogger=INFO, console
|
log4j.rootLogger=DEBUG, console
|
||||||
#log4j.rootLogger=INFO, console, file
|
#log4j.rootLogger=INFO, console, file
|
||||||
|
|
||||||
log4j.appender.console=org.apache.log4j.ConsoleAppender
|
log4j.appender.console=org.apache.log4j.ConsoleAppender
|
||||||
|
|||||||
@@ -89,21 +89,7 @@ var TableManaged = function () {
|
|||||||
// datatable.reload(null, false);
|
// datatable.reload(null, false);
|
||||||
|
|
||||||
});
|
});
|
||||||
$("#editUser").on('click',function(){
|
|
||||||
var arr= setSelectAll();
|
|
||||||
if(arr[0]>1){
|
|
||||||
|
|
||||||
appcommon.alert("每次只能修改一条记录",0,2000);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(arr[0]==0){
|
|
||||||
appcommon.alert("请选择记录",0,2000);
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
toEditUserPage(arr[1]);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#delUser").on('click',function(){
|
$("#delUser").on('click',function(){
|
||||||
var arr = setSelectAll();
|
var arr = setSelectAll();
|
||||||
@@ -340,36 +326,7 @@ function addUserSubmit(){
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取待修改用户的值
|
|
||||||
*/
|
|
||||||
function toEditUserPage(username){
|
|
||||||
$.ajax({
|
|
||||||
url:'/admin/toEditUserPage',
|
|
||||||
type:'post',
|
|
||||||
data:'username='+username,
|
|
||||||
async : true,// 默认为true 异步
|
|
||||||
error:function(){
|
|
||||||
|
|
||||||
appcommon.alert("系统异常",2);
|
|
||||||
},
|
|
||||||
success:function(data){
|
|
||||||
var data = $.parseJSON(data);
|
|
||||||
|
|
||||||
$("#editUser-form input[name=company]").val(data.company);
|
|
||||||
$("#editUser-form input[name=email]").val(data.email);
|
|
||||||
$("#editUser-form input[name=position]").val(data.position);
|
|
||||||
$("#editUser-form input[name=fax]").val(data.fax);
|
|
||||||
$("#editUser-form input[name=mobile]").val(data.mobile);
|
|
||||||
$("#editUser-form input[name=realName]").val(data.realName);
|
|
||||||
$("#editUser-form input[name=username1]").val(data.username);
|
|
||||||
$("#editUser-form input[name=username]").val(data.username);
|
|
||||||
$('#Modal-EditUser').modal('show')
|
|
||||||
|
|
||||||
TableManaged.editUserValidator();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -20,80 +20,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row" style="padding-top: 10px;">
|
|
||||||
<!-- 单位名称 -->
|
|
||||||
<div class="col-md-8 input-lg">
|
|
||||||
<div class="form-group form-group-lg">
|
|
||||||
<label class="col-sm-4 control-label">单位名称</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<input type="text" class="form-control input-lg" id="company" placeholder="单位名称" name="company" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row" style="padding-top: 10px;">
|
|
||||||
<!-- 职务 -->
|
|
||||||
<div class="col-md-8 input-lg">
|
|
||||||
<div class="form-group form-group-lg">
|
|
||||||
<label class="col-sm-4 control-label">职务</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<input type="text" class="form-control input-lg" id="position" placeholder="职务" name="position" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row" style="padding-top: 10px;">
|
|
||||||
<!-- 姓名 -->
|
|
||||||
<div class="col-md-8 input-lg">
|
|
||||||
<div class="form-group form-group-lg">
|
|
||||||
<label class="col-sm-4 control-label">姓名</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<input type="text" class="form-control input-lg" id="realName" placeholder="姓名" name="realName" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row" style="padding-top: 10px;">
|
|
||||||
<!-- 联系电话 -->
|
|
||||||
<div class="col-md-8 input-lg">
|
|
||||||
<div class="form-group form-group-lg">
|
|
||||||
<label class="col-sm-4 control-label">联系电话</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<input type="text" class="form-control input-lg" id="mobile" placeholder="联系电话" name="mobile" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row" style="padding-top: 10px;">
|
|
||||||
<!-- 邮箱 -->
|
|
||||||
<div class="col-md-8 input-lg">
|
|
||||||
<div class="form-group form-group-lg">
|
|
||||||
<label class="col-sm-4 control-label">邮箱</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<input type="text" class="form-control input-lg" id="email" placeholder="邮箱" name="email" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row" style="padding-top: 10px;">
|
|
||||||
<!-- 传真 -->
|
|
||||||
<div class="col-md-8 input-lg">
|
|
||||||
<div class="form-group form-group-lg">
|
|
||||||
<label class="col-sm-4 control-label">传真</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<input type="text" class="form-control input-lg" id="fax" placeholder="传真" name="fax" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
|
|||||||
@@ -1,110 +0,0 @@
|
|||||||
<div>
|
|
||||||
<form id="editUser-form" class="form-horizontal" action="">
|
|
||||||
<div class="modal hide fade " id="Modal-EditUser">
|
|
||||||
<div class="modal-dialog">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"></button>
|
|
||||||
<h4 class="modal-title">添加用户</h4>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<div class="row" style="padding-top: 10px;">
|
|
||||||
<!-- 登录用户名 -->
|
|
||||||
<div class="col-md-8 input-lg">
|
|
||||||
<div class="form-group form-group-lg">
|
|
||||||
<label class="col-sm-4 control-label">登录用户名</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<input type="text" class="form-control input-lg" id="username1" placeholder="登录用户名" disabled name="username1" />
|
|
||||||
<input type="text" style="display:none" id="username" name="username" />
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row" style="padding-top: 10px;">
|
|
||||||
<!-- 单位名称 -->
|
|
||||||
<div class="col-md-8 input-lg">
|
|
||||||
<div class="form-group form-group-lg">
|
|
||||||
<label class="col-sm-4 control-label">单位名称</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<input type="text" class="form-control input-lg" id="company" placeholder="单位名称" name="company" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row" style="padding-top: 10px;">
|
|
||||||
<!-- 职务 -->
|
|
||||||
<div class="col-md-8 input-lg">
|
|
||||||
<div class="form-group form-group-lg">
|
|
||||||
<label class="col-sm-4 control-label">职务</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<input type="text" class="form-control input-lg" id="position" placeholder="职务" name="position" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row" style="padding-top: 10px;">
|
|
||||||
<!-- 姓名 -->
|
|
||||||
<div class="col-md-8 input-lg">
|
|
||||||
<div class="form-group form-group-lg">
|
|
||||||
<label class="col-sm-4 control-label">姓名</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<input type="text" class="form-control input-lg" id="realName" placeholder="姓名" name="realName" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row" style="padding-top: 10px;">
|
|
||||||
<!-- 联系电话 -->
|
|
||||||
<div class="col-md-8 input-lg">
|
|
||||||
<div class="form-group form-group-lg">
|
|
||||||
<label class="col-sm-4 control-label">联系电话</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<input type="text" class="form-control input-lg" id="mobile" placeholder="联系电话" name="mobile" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row" style="padding-top: 10px;">
|
|
||||||
<!-- 邮箱 -->
|
|
||||||
<div class="col-md-8 input-lg">
|
|
||||||
<div class="form-group form-group-lg">
|
|
||||||
<label class="col-sm-4 control-label">邮箱</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<input type="text" class="form-control input-lg" id="email" placeholder="邮箱" name="email" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row" style="padding-top: 10px;">
|
|
||||||
<!-- 传真 -->
|
|
||||||
<div class="col-md-8 input-lg">
|
|
||||||
<div class="form-group form-group-lg">
|
|
||||||
<label class="col-sm-4 control-label">传真</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<input type="text" class="form-control input-lg" id="fax" placeholder="传真" name="fax" />
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button type="button" class="btn btn-default pull-right" data-dismiss="modal">关闭</button>
|
|
||||||
<button type="button" class="btn btn-primary" onclick="editUserSubmit();" >保存</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
File diff suppressed because one or more lines are too long
65
demo-shiro-web/test
Normal file
65
demo-shiro-web/test
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* 权限认证,为当前登录的Subject授予角色和权限
|
||||||
|
* @see:本例中该方法的调用时机为需授权资源被访问时
|
||||||
|
* @see :并且每次访问需授权资源时都会执行该方法中的逻辑,这表明本例中默认并未启用AuthorizationCache
|
||||||
|
* @see :如果连续访问同一个URL(比如刷新),该方法不会被重复调用,Shiro有一个时间间隔(也就是cache时间,在ehcache-shiro.xml中配置),超过这个时间间隔再刷新页面,该方法会被执行
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
|
||||||
|
//获取当前登录输入的用户名,等价于(String) principalCollection.fromRealm(getName()).iterator().next();
|
||||||
|
String loginName = (String)super.getAvailablePrincipal(principalCollection);
|
||||||
|
//到数据库查是否有此对象
|
||||||
|
ShiroUser user= shiroUserService.findByUsername(loginName);
|
||||||
|
if(user!=null){
|
||||||
|
//权限信息对象info,用来存放查出的用户的所有的角色(role)及权限(permission)
|
||||||
|
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
|
||||||
|
//用户的角色集合
|
||||||
|
info.setRoles(user.getRolesName());
|
||||||
|
List<ShiroRole> roleList=user.getRoleList();
|
||||||
|
for (ShiroRole role : roleList) {
|
||||||
|
info.addStringPermissions(role.getPermissionsName());
|
||||||
|
}
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
// 返回null的话,就会导致任何用户访问被拦截的请求时,都会自动跳转到unauthorizedUrl指定的地址
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录认证
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AuthenticationInfo doGetAuthenticationInfo(
|
||||||
|
AuthenticationToken authenticationToken) throws AuthenticationException {
|
||||||
|
|
||||||
|
//UsernamePasswordToken对象用来存放提交的登录信息
|
||||||
|
UsernamePasswordToken token=(UsernamePasswordToken) authenticationToken;
|
||||||
|
|
||||||
|
//查出是否有此用户
|
||||||
|
ShiroUser user= shiroUserService.findByUsername(token.getUsername());
|
||||||
|
|
||||||
|
if(user==null){
|
||||||
|
throw new UnknownAccountException();//账户不存在
|
||||||
|
}
|
||||||
|
if(user!=null&&user.getStatus().equals(Constants.userStatus_2)){
|
||||||
|
|
||||||
|
throw new LockedAccountException(); //账户被锁
|
||||||
|
}
|
||||||
|
if(user!=null&&user.getStatus().equals(Constants.userStatus_0)){
|
||||||
|
|
||||||
|
throw new DisabledAccountException();//账户不存在
|
||||||
|
}
|
||||||
|
if(user!=null&&user.getStatus().equals(Constants.userStatus_1)){
|
||||||
|
// 若存在,将此用户存放到登录认证info中,无需自己做密码对比,Shiro会为我们进行密码对比校验
|
||||||
|
return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), ByteSource.Util.bytes("www"),getName());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
<groupId>org.apache.shiro</groupId>
|
<groupId>org.apache.shiro</groupId>
|
||||||
<artifactId>shiro-ehcache</artifactId>
|
<artifactId>shiro-ehcache</artifactId>
|
||||||
<version>${shiro.version}</version>
|
<version>${shiro.version}</version>
|
||||||
<scope>provided</scope>
|
<!-- <scope>provided</scope> -->
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.shiro</groupId>
|
<groupId>org.apache.shiro</groupId>
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package com.xinwei.spring.boot.autoconfigure.shiro;
|
package com.xinwei.spring.boot.autoconfigure.shiro;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import org.apache.shiro.authc.AuthenticationInfo;
|
import org.apache.shiro.authc.AuthenticationInfo;
|
||||||
import org.apache.shiro.authc.AuthenticationToken;
|
import org.apache.shiro.authc.AuthenticationToken;
|
||||||
import org.apache.shiro.authc.ExcessiveAttemptsException;
|
import org.apache.shiro.authc.ExcessiveAttemptsException;
|
||||||
@@ -10,14 +12,12 @@ import org.apache.shiro.cache.CacheManager;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher {
|
public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher {
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(RetryLimitHashedCredentialsMatcher.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(RetryLimitHashedCredentialsMatcher.class);
|
||||||
|
|
||||||
private Cache<String, AtomicInteger> passwordRetryCache;
|
private Cache<String, AtomicInteger> passwordRetryCache;
|
||||||
private int retryMax = 5;
|
private int retryMax;
|
||||||
|
|
||||||
public RetryLimitHashedCredentialsMatcher(CacheManager cacheManager) {
|
public RetryLimitHashedCredentialsMatcher(CacheManager cacheManager) {
|
||||||
passwordRetryCache = cacheManager.getCache("passwordRetryCache");
|
passwordRetryCache = cacheManager.getCache("passwordRetryCache");
|
||||||
@@ -27,15 +27,23 @@ public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher
|
|||||||
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) throws ExcessiveAttemptsException {
|
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) throws ExcessiveAttemptsException {
|
||||||
String username = (String)token.getPrincipal();
|
String username = (String)token.getPrincipal();
|
||||||
AtomicInteger retryCount = passwordRetryCache.get(username);
|
AtomicInteger retryCount = passwordRetryCache.get(username);
|
||||||
|
|
||||||
if(retryCount == null) {
|
if(retryCount == null) {
|
||||||
retryCount = new AtomicInteger(0);
|
retryCount = new AtomicInteger(0);
|
||||||
passwordRetryCache.put(username, retryCount);
|
passwordRetryCache.put(username, retryCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(retryCount.incrementAndGet() > retryMax) {
|
if(retryCount.incrementAndGet() > retryMax) {
|
||||||
throw new ExcessiveAttemptsException("您已连续错误达" + retryMax + "次!请10分钟后再试");
|
throw new ExcessiveAttemptsException("您已连续错误达" + retryMax + "次!请N分钟后再试");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用redis 管理登录次数时, 需要此段代码(注意:只有redis需要,内存和ehcache不需要)。
|
||||||
|
*/
|
||||||
|
if( passwordRetryCache.getClass().getName().contains("RedisCache")){
|
||||||
|
passwordRetryCache.put(username, retryCount);
|
||||||
|
}
|
||||||
|
|
||||||
boolean matches = super.doCredentialsMatch(token, info);
|
boolean matches = super.doCredentialsMatch(token, info);
|
||||||
if(matches) {
|
if(matches) {
|
||||||
passwordRetryCache.remove(username);
|
passwordRetryCache.remove(username);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import org.apache.shiro.cache.CacheManager;
|
|||||||
import org.apache.shiro.cache.ehcache.EhCacheManager;
|
import org.apache.shiro.cache.ehcache.EhCacheManager;
|
||||||
import org.apache.shiro.crypto.CipherService;
|
import org.apache.shiro.crypto.CipherService;
|
||||||
import org.apache.shiro.io.Serializer;
|
import org.apache.shiro.io.Serializer;
|
||||||
|
import org.apache.shiro.mgt.DefaultSecurityManager;
|
||||||
import org.apache.shiro.mgt.RememberMeManager;
|
import org.apache.shiro.mgt.RememberMeManager;
|
||||||
import org.apache.shiro.mgt.SecurityManager;
|
import org.apache.shiro.mgt.SecurityManager;
|
||||||
import org.apache.shiro.realm.AuthenticatingRealm;
|
import org.apache.shiro.realm.AuthenticatingRealm;
|
||||||
@@ -12,19 +13,24 @@ import org.apache.shiro.realm.Realm;
|
|||||||
import org.apache.shiro.realm.jdbc.JdbcRealm;
|
import org.apache.shiro.realm.jdbc.JdbcRealm;
|
||||||
import org.apache.shiro.session.SessionListener;
|
import org.apache.shiro.session.SessionListener;
|
||||||
import org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler;
|
import org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler;
|
||||||
|
import org.apache.shiro.session.mgt.SessionManager;
|
||||||
import org.apache.shiro.session.mgt.SessionValidationScheduler;
|
import org.apache.shiro.session.mgt.SessionValidationScheduler;
|
||||||
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
|
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
|
||||||
import org.apache.shiro.session.mgt.eis.SessionDAO;
|
import org.apache.shiro.session.mgt.eis.SessionDAO;
|
||||||
import org.apache.shiro.session.mgt.eis.SessionIdGenerator;
|
import org.apache.shiro.session.mgt.eis.SessionIdGenerator;
|
||||||
import org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler;
|
import org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler;
|
||||||
|
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.spring.web.ShiroFilterFactoryBean;
|
||||||
import org.apache.shiro.subject.PrincipalCollection;
|
import org.apache.shiro.subject.PrincipalCollection;
|
||||||
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
|
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
|
||||||
import org.apache.shiro.web.mgt.CookieRememberMeManager;
|
import org.apache.shiro.web.mgt.CookieRememberMeManager;
|
||||||
|
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
|
||||||
import org.apache.shiro.web.servlet.Cookie;
|
import org.apache.shiro.web.servlet.Cookie;
|
||||||
import org.apache.shiro.web.servlet.SimpleCookie;
|
import org.apache.shiro.web.servlet.SimpleCookie;
|
||||||
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
|
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
|
||||||
import org.apache.shiro.web.session.mgt.WebSessionManager;
|
import org.apache.shiro.web.session.mgt.WebSessionManager;
|
||||||
|
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
@@ -85,6 +91,8 @@ public class ShiroAutoConfiguration {
|
|||||||
|
|
||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
private Collection<SessionListener> listeners;
|
private Collection<SessionListener> listeners;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Bean(name = "mainRealm")
|
@Bean(name = "mainRealm")
|
||||||
@ConditionalOnMissingBean(name = "mainRealm")
|
@ConditionalOnMissingBean(name = "mainRealm")
|
||||||
@@ -121,17 +129,6 @@ public class ShiroAutoConfiguration {
|
|||||||
return realm;
|
return realm;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean(name = "shiroCacheManager")
|
|
||||||
@ConditionalOnClass(name = {"org.apache.shiro.cache.ehcache.EhCacheManager"})
|
|
||||||
@ConditionalOnMissingBean(name = "shiroCacheManager")
|
|
||||||
public CacheManager ehcacheManager() {
|
|
||||||
EhCacheManager ehCacheManager = new EhCacheManager();
|
|
||||||
ShiroProperties.Ehcache ehcache = properties.getEhcache();
|
|
||||||
if (ehcache.getCacheManagerConfigFile() != null) {
|
|
||||||
ehCacheManager.setCacheManagerConfigFile(ehcache.getCacheManagerConfigFile());
|
|
||||||
}
|
|
||||||
return ehCacheManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean(Cookie.class)
|
@ConditionalOnMissingBean(Cookie.class)
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package com.xinwei.spring.boot.autoconfigure.shiro;
|
|||||||
|
|
||||||
import org.apache.shiro.cache.CacheManager;
|
import org.apache.shiro.cache.CacheManager;
|
||||||
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
|
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
|
||||||
import org.apache.shiro.cache.ehcache.EhCacheManager;
|
|
||||||
import org.apache.shiro.mgt.DefaultSecurityManager;
|
import org.apache.shiro.mgt.DefaultSecurityManager;
|
||||||
import org.apache.shiro.mgt.RememberMeManager;
|
import org.apache.shiro.mgt.RememberMeManager;
|
||||||
import org.apache.shiro.realm.Realm;
|
import org.apache.shiro.realm.Realm;
|
||||||
@@ -11,13 +10,10 @@ import org.apache.shiro.spring.LifecycleBeanPostProcessor;
|
|||||||
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
|
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
|
||||||
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
|
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
|
||||||
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
|
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.DependsOn;
|
import org.springframework.context.annotation.DependsOn;
|
||||||
import org.springframework.core.annotation.Order;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This guy is lazy, nothing left.
|
* This guy is lazy, nothing left.
|
||||||
@@ -41,16 +37,7 @@ public class ShiroConfiguration {
|
|||||||
return defaultAdvisorAutoProxyCreator;
|
return defaultAdvisorAutoProxyCreator;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* (基于内存的)用户授权信息Cache
|
|
||||||
*/
|
|
||||||
@Bean(name = "shiroCacheManager")
|
|
||||||
@ConditionalOnMissingBean(name = "shiroCacheManager")
|
|
||||||
@ConditionalOnMissingClass(value = {"org.apache.shiro.cache.ehcache.EhCacheManager"})
|
|
||||||
public CacheManager shiroCacheManager() {
|
|
||||||
return new MemoryConstrainedCacheManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean(name = "securityManager")
|
@Bean(name = "securityManager")
|
||||||
@DependsOn(value = {"shiroCacheManager", "rememberMeManager", "mainRealm"})
|
@DependsOn(value = {"shiroCacheManager", "rememberMeManager", "mainRealm"})
|
||||||
public DefaultSecurityManager securityManager(Realm realm, RememberMeManager rememberMeManager,
|
public DefaultSecurityManager securityManager(Realm realm, RememberMeManager rememberMeManager,
|
||||||
@@ -70,4 +57,6 @@ public class ShiroConfiguration {
|
|||||||
aasa.setSecurityManager(securityManager);
|
aasa.setSecurityManager(securityManager);
|
||||||
return aasa;
|
return aasa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,39 @@ public class ShiroProperties {
|
|||||||
*/
|
*/
|
||||||
private int retryMax = 100;
|
private int retryMax = 100;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码重试次数达到上限后,锁定时间(该参数仅适用于 redis管理cache)
|
||||||
|
*/
|
||||||
|
private int retryExpireTimeRedis = 5;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 权限 缓存过期时间 (该参数仅适用于 redis管理cache)
|
||||||
|
*/
|
||||||
|
|
||||||
|
private int AuthorizationExpireTimeRedis = 10;
|
||||||
|
|
||||||
|
|
||||||
|
public int getRetryExpireTimeRedis() {
|
||||||
|
return retryExpireTimeRedis;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRetryExpireTimeRedis(int retryExpireTimeRedis) {
|
||||||
|
this.retryExpireTimeRedis = retryExpireTimeRedis;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public int getAuthorizationExpireTimeRedis() {
|
||||||
|
return AuthorizationExpireTimeRedis;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthorizationExpireTimeRedis(int authorizationExpireTimeRedis) {
|
||||||
|
AuthorizationExpireTimeRedis = authorizationExpireTimeRedis;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private boolean storedCredentialsHexEncoded = true;
|
private boolean storedCredentialsHexEncoded = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -140,9 +173,11 @@ public class ShiroProperties {
|
|||||||
|
|
||||||
public static class Ehcache {
|
public static class Ehcache {
|
||||||
|
|
||||||
private String cacheManagerConfigFile = "classpath:org/apache/shiro/cache/ehcache/ehcache.xml";
|
// private String cacheManagerConfigFile = "classpath:org/apache/shiro/cache/ehcache/ehcache.xml";
|
||||||
|
|
||||||
public String getCacheManagerConfigFile() {
|
private String cacheManagerConfigFile = "classpath:ehcache.xml";
|
||||||
|
|
||||||
|
public String getCacheManagerConfigFile() {
|
||||||
return cacheManagerConfigFile;
|
return cacheManagerConfigFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
27
sql/shiro_function.sql
Normal file
27
sql/shiro_function.sql
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
-- Query: SELECT * FROM shiroDemo.shiro_function
|
||||||
|
LIMIT 0, 1000
|
||||||
|
|
||||||
|
-- Date: 2018-02-08 16:40
|
||||||
|
*/
|
||||||
|
INSERT INTO `shiro_function` (`id`,`create_time`,`function_name`,`permission_name`,`pid`) VALUES (1,NULL,'演示系统','1',0);
|
||||||
|
INSERT INTO `shiro_function` (`id`,`create_time`,`function_name`,`permission_name`,`pid`) VALUES (29,NULL,'系统管理功能','4',1);
|
||||||
|
INSERT INTO `shiro_function` (`id`,`create_time`,`function_name`,`permission_name`,`pid`) VALUES (30,NULL,'用户管理','4-1',29);
|
||||||
|
INSERT INTO `shiro_function` (`id`,`create_time`,`function_name`,`permission_name`,`pid`) VALUES (31,'2016-08-17 10:16:48','添加','4-1-add',30);
|
||||||
|
INSERT INTO `shiro_function` (`id`,`create_time`,`function_name`,`permission_name`,`pid`) VALUES (32,NULL,'功能管理','4-2',29);
|
||||||
|
INSERT INTO `shiro_function` (`id`,`create_time`,`function_name`,`permission_name`,`pid`) VALUES (34,NULL,'角色管理','4-3',29);
|
||||||
|
INSERT INTO `shiro_function` (`id`,`create_time`,`function_name`,`permission_name`,`pid`) VALUES (43,'2016-08-17 10:16:16','查询','4-1-search',30);
|
||||||
|
INSERT INTO `shiro_function` (`id`,`create_time`,`function_name`,`permission_name`,`pid`) VALUES (44,'2016-08-17 10:17:07','修改','4-1-edit',30);
|
||||||
|
INSERT INTO `shiro_function` (`id`,`create_time`,`function_name`,`permission_name`,`pid`) VALUES (45,'2016-08-17 10:17:13','审核','4-1-audit',30);
|
||||||
|
INSERT INTO `shiro_function` (`id`,`create_time`,`function_name`,`permission_name`,`pid`) VALUES (46,'2016-08-17 10:17:45','添加角色','4-1-role',30);
|
||||||
|
INSERT INTO `shiro_function` (`id`,`create_time`,`function_name`,`permission_name`,`pid`) VALUES (49,'2016-08-17 14:20:35','操作(增加,修改,删除,赋权限)','4-3-operate',34);
|
||||||
|
INSERT INTO `shiro_function` (`id`,`create_time`,`function_name`,`permission_name`,`pid`) VALUES (67,'2018-02-05 12:41:19','添加','4-2-add',32);
|
||||||
|
INSERT INTO `shiro_function` (`id`,`create_time`,`function_name`,`permission_name`,`pid`) VALUES (68,'2018-02-05 12:41:34','修改','4-2-edit',32);
|
||||||
|
INSERT INTO `shiro_function` (`id`,`create_time`,`function_name`,`permission_name`,`pid`) VALUES (69,'2018-02-05 12:41:44','删除','4-2-del',32);
|
||||||
|
INSERT INTO `shiro_function` (`id`,`create_time`,`function_name`,`permission_name`,`pid`) VALUES (70,'2018-02-05 12:45:35','添加','4-3-add',34);
|
||||||
|
INSERT INTO `shiro_function` (`id`,`create_time`,`function_name`,`permission_name`,`pid`) VALUES (72,'2018-02-05 12:46:15','删除','4-3-del',34);
|
||||||
|
INSERT INTO `shiro_function` (`id`,`create_time`,`function_name`,`permission_name`,`pid`) VALUES (73,'2018-02-05 12:46:23','修改','4-3-edit',34);
|
||||||
|
INSERT INTO `shiro_function` (`id`,`create_time`,`function_name`,`permission_name`,`pid`) VALUES (74,'2018-02-05 12:47:10','角色添加功能','4-3-role-func',34);
|
||||||
|
INSERT INTO `shiro_function` (`id`,`create_time`,`function_name`,`permission_name`,`pid`) VALUES (75,'2018-02-05 12:54:40','测试菜单','1-test',1);
|
||||||
|
INSERT INTO `shiro_function` (`id`,`create_time`,`function_name`,`permission_name`,`pid`) VALUES (76,'2018-02-05 12:55:14','测试-1','2-1',75);
|
||||||
|
INSERT INTO `shiro_function` (`id`,`create_time`,`function_name`,`permission_name`,`pid`) VALUES (77,'2018-02-05 12:57:17','测试2','2-2',75);
|
||||||
7
sql/shiro_role.sql
Normal file
7
sql/shiro_role.sql
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/*
|
||||||
|
-- Query: SELECT * FROM shiroDemo.shiro_role
|
||||||
|
LIMIT 0, 1000
|
||||||
|
|
||||||
|
-- Date: 2018-02-08 16:41
|
||||||
|
*/
|
||||||
|
INSERT INTO `shiro_role` (`id`,`create_time`,`role_name`) VALUES (1,'2018-02-05 11:22:09','管理员');
|
||||||
23
sql/shiro_role_function.sql
Normal file
23
sql/shiro_role_function.sql
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
-- Query: SELECT * FROM shiroDemo.shiro_role_function
|
||||||
|
LIMIT 0, 1000
|
||||||
|
|
||||||
|
-- Date: 2018-02-08 16:41
|
||||||
|
*/
|
||||||
|
INSERT INTO `shiro_role_function` (`role_id`,`function_id`) VALUES (1,1);
|
||||||
|
INSERT INTO `shiro_role_function` (`role_id`,`function_id`) VALUES (1,29);
|
||||||
|
INSERT INTO `shiro_role_function` (`role_id`,`function_id`) VALUES (1,30);
|
||||||
|
INSERT INTO `shiro_role_function` (`role_id`,`function_id`) VALUES (1,31);
|
||||||
|
INSERT INTO `shiro_role_function` (`role_id`,`function_id`) VALUES (1,43);
|
||||||
|
INSERT INTO `shiro_role_function` (`role_id`,`function_id`) VALUES (1,44);
|
||||||
|
INSERT INTO `shiro_role_function` (`role_id`,`function_id`) VALUES (1,45);
|
||||||
|
INSERT INTO `shiro_role_function` (`role_id`,`function_id`) VALUES (1,46);
|
||||||
|
INSERT INTO `shiro_role_function` (`role_id`,`function_id`) VALUES (1,32);
|
||||||
|
INSERT INTO `shiro_role_function` (`role_id`,`function_id`) VALUES (1,67);
|
||||||
|
INSERT INTO `shiro_role_function` (`role_id`,`function_id`) VALUES (1,68);
|
||||||
|
INSERT INTO `shiro_role_function` (`role_id`,`function_id`) VALUES (1,69);
|
||||||
|
INSERT INTO `shiro_role_function` (`role_id`,`function_id`) VALUES (1,34);
|
||||||
|
INSERT INTO `shiro_role_function` (`role_id`,`function_id`) VALUES (1,49);
|
||||||
|
INSERT INTO `shiro_role_function` (`role_id`,`function_id`) VALUES (1,75);
|
||||||
|
INSERT INTO `shiro_role_function` (`role_id`,`function_id`) VALUES (1,76);
|
||||||
|
INSERT INTO `shiro_role_function` (`role_id`,`function_id`) VALUES (1,77);
|
||||||
8
sql/shiro_user.sql
Normal file
8
sql/shiro_user.sql
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/*
|
||||||
|
-- Query: SELECT * FROM shiroDemo.shiro_user
|
||||||
|
LIMIT 0, 1000
|
||||||
|
|
||||||
|
-- Date: 2018-02-08 16:41
|
||||||
|
*/
|
||||||
|
INSERT INTO `shiro_user` (`id`,`create_time`,`password`,`status`,`username`) VALUES (2,NULL,'5VIGn1Yz66kevrJEWjT4pw==','1','admin');
|
||||||
|
INSERT INTO `shiro_user` (`id`,`create_time`,`password`,`status`,`username`) VALUES (47,'2018-02-05 17:05:02','cSbmvFebb1glkQvPG02RgA==','1','test');
|
||||||
8
sql/shiro_user_role.sql
Normal file
8
sql/shiro_user_role.sql
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/*
|
||||||
|
-- Query: SELECT * FROM shiroDemo.shiro_user_role
|
||||||
|
LIMIT 0, 1000
|
||||||
|
|
||||||
|
-- Date: 2018-02-08 16:42
|
||||||
|
*/
|
||||||
|
INSERT INTO `shiro_user_role` (`user_id`,`role_id`) VALUES (2,1);
|
||||||
|
INSERT INTO `shiro_user_role` (`user_id`,`role_id`) VALUES (47,1);
|
||||||
Reference in New Issue
Block a user