发表于: 2018-03-21 19:32:22
1 483
今天完成的事情:大致上看懂了一个完整shiro框架的布局:
<!-- Shiro生命周期处理器-->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/u/login.shtml" />
<!-- TODO 待提取 -->
<property name="successUrl" value="/" />
<property name="unauthorizedUrl" value="/?login" />
<!-- 初始配置,现采用自定义 -->
<!-- <property name="filterChainDefinitions" >-->
<!-- <value>-->
<!-- /** = anon-->
<!-- /page/login.jsp = anon-->
<!-- /page/register/* = anon-->
<!-- /page/index.jsp = authc-->
<!-- /page/addItem* = authc,roles[数据管理员]-->
<!-- /page/file* = authc,roleOR[普通用户,数据管理员]-->
<!-- /page/listItems* = authc,roleOR[数据管理员,普通用户]-->
<!-- /page/showItem* = authc,roleOR[数据管理员,普通用户]-->
<!-- /page/updateItem*=authc,roles[数据管理员]-->
<!-- </value>-->
<!-- </property>-->
<!-- 读取初始自定义权限内容-->
<property name="filterChainDefinitions" value="#{shiroManager.loadFilterChainDefinitions()}"/>
<property name="filters">
<util:map>
<entry key="login" value-ref="login"/>
<entry key="role" value-ref="role"/>
<entry key="simple" value-ref="simple"/>
<entry key="permission" value-ref="permission"/>
<entry key="kickout" value-ref="kickoutSessionFilter"/>
</util:map>
</property>
</bean>
<!--
自定义角色过滤器 支持多个角色可以访问同一个资源 eg:/home.jsp = authc,roleOR[admin,user]
用户有admin或者user角色 就可以访问
-->
<!-- 认证数据库存储-->
<!--动态加载拦截器链配置-->
<bean id="shiroManager" class="com.sojson.core.shiro.service.impl.ShiroManagerImpl"/>
<bean id="login" class="com.sojson.core.shiro.filter.LoginFilter"/>
<bean id="role" class="com.sojson.core.shiro.filter.RoleFilter"/>
<bean id="permission" class="com.sojson.core.shiro.filter.PermissionFilter"/>
<bean id="simple" class="com.sojson.core.shiro.filter.SimpleAuthFilter"/>
<!-- kickout拦截器 校验单个用户是否多次登录 -->
<bean id="kickoutSessionFilter" class="com.sojson.core.shiro.filter.KickoutSessionFilter">
<property name="kickoutUrl" value="/u/login.shtml?kickout"/>
</bean>
<!-- 静态注入 jedisShiroSessionRepository-->
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod" value="com.sojson.core.shiro.filter.KickoutSessionFilter.setShiroSessionRepository"/>
<property name="arguments" ref="jedisShiroSessionRepository"/>
</bean>
<!-- 核心安全管理器(静态注入) -->
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>
<property name="arguments" ref="securityManager"/>
</bean>
<!-- 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="sampleRealm"/>
<property name="sessionManager" ref="sessionManager"/>
<property name="rememberMeManager" ref="rememberMeManager"/>
<property name="cacheManager" ref="customShiroCacheManager"/>
</bean>
<!-- 授权 认证 -->
<bean id="sampleRealm" class="com.sojson.core.shiro.token.SampleRealm" />
<!-- 会话管理器 -->
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<!-- 相隔多久检查一次session的有效性 -->
<property name="sessionValidationInterval" value="1800000"/>
<!-- session 有效时间为半小时 (毫秒单位)-->
<property name="globalSessionTimeout" value="1800000"/>
<property name="sessionDAO" ref="customShiroSessionDAO"/>
<!-- session 监听,可以多个。 -->
<property name="sessionListeners">
<list>
<ref bean="customSessionListener"/>
</list>
</property>
<!-- 间隔多少时间检查,不配置是60分钟 -->
<property name="sessionValidationScheduler" ref="sessionValidationScheduler"/>
<!-- 是否开启 检测,默认开启 -->
<property name="sessionValidationSchedulerEnabled" value="true"/>
<!-- 是否删除无效的,默认也是开启 -->
<property name="deleteInvalidSessions" value="true"/>
<!-- 会话Cookie模板 -->
<property name="sessionIdCookie" ref="sessionIdCookie"/>
</bean>
<!-- 会话验证调度器 -->
<bean id="sessionValidationScheduler" class="org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler">
<!-- 间隔多少时间检查,不配置是60分钟 -->
<property name="interval" value="${session.validate.timespan}"/>
<property name="sessionManager" ref="sessionManager"/>
</bean>
<!-- 会话Cookie模板 -->
<bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<!--cookie的name,比如说jnshu -->
<!--<property name="name" value="jnshu"/>-->
<!--也可以通过构造方法注入:-->
<constructor-arg value="v_v-s-baidu"/>
<!--如果设置为true,则客户端不会暴露给客户端脚本代码,
使用HttpOnly cookie有助于减少某些类型的跨站点脚本攻击;
此特性需要实现了Servlet 2.5 MR6及以上版本的规范的Servlet容器支持-->
<property name="httpOnly" value="true"/>
<!--cookie的有效时间 -->
<!--设置Cookie的过期时间,秒为单位,默认-1表示关闭浏览器时过期Cookie-->
<property name="maxAge" value="-1"/>
<!-- 配置存储Session Cookie的domain(一级域名) 默认空,即当前访问的域名;
<property name="domain" value=".jnshu.com"/>
-->
</bean>
<!-- rememberMe管理器 -->
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
<!-- rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)-->
<property name="cipherKey"
value="#{T(org.apache.shiro.codec.Base64).decode('3AvVhmFLUs0KTA3Kprsdag==')}"/>
<property name="cookie" ref="rememberMeCookie"/>
</bean>
<!-- 用户信息记住我功能的相关配置 -->
<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<constructor-arg value="v_v-re-baidu"/>
<property name="httpOnly" value="true"/>
<!-- 配置存储rememberMe Cookie的domain为 一级域名
<property name="domain" value=".itboy.net"/>
-->
<property name="maxAge" value="2592000"/><!-- 30天时间,记住我30天 -->
</bean>
<!-- session持久化(缓存) -->
<bean id="customShiroSessionDAO" class="com.sojson.core.shiro.CustomShiroSessionDAO">
<property name="shiroSessionRepository" ref="jedisShiroSessionRepository"/>
<property name="sessionIdGenerator" ref="sessionIdGenerator"/>
</bean>
<!-- 会话Session ID生成器 -->
<bean id="sessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator"/>
<!-- 手动操作Session,管理Session -->
<bean id="customSessionManager" class="com.sojson.core.shiro.session.CustomSessionManager">
<property name="shiroSessionRepository" ref="jedisShiroSessionRepository"/>
<property name="customShiroSessionDAO" ref="customShiroSessionDAO"/>
</bean>
<!-- shiro监听器,管理session生命周期(基于jedis缓存操作session) -->
<bean id="customSessionListener" class="com.sojson.core.shiro.listenter.CustomSessionListener">
<property name="shiroSessionRepository" ref="jedisShiroSessionRepository"/>
</bean>
<!-- session 创建、删除、查询(基于jedis) -->
<bean id="jedisShiroSessionRepository" class="com.sojson.core.shiro.cache.JedisShiroSessionRepository" >
<property name="jedisManager" ref="jedisManager"/>
</bean>
<!-- 用户缓存 -->
<bean id="customShiroCacheManager" class="com.sojson.core.shiro.cache.impl.CustomShiroCacheManager">
<property name="shiroCacheManager" ref="jedisShiroCacheManager"/>
</bean>
<!-- shiro 缓存实现,对ShiroCacheManager,我是采用redis的实现 -->
<bean id="jedisShiroCacheManager" class="com.sojson.core.shiro.cache.impl.JedisShiroCacheManager">
<property name="jedisManager" ref="jedisManager"/>
</bean>
<!-- redis 底层操作 -->
<bean id="jedisManager" class="com.sojson.core.shiro.cache.JedisManager">
<!--由spring整合redis-->
<property name="jedisPool" ref="jedisPool"/>
</bean>
授权类:
public class SampleRealm extends AuthorizingRealm {
@Autowired
UUserService userService;
@Autowired
PermissionService permissionService;
@Autowired
RoleService roleService;
public SampleRealm() {
super();
}
/**
* 认证信息,主要针对用户登录,
*/
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken authcToken) throws AuthenticationException {
ShiroToken token = (ShiroToken) authcToken;
UUser user = userService.login(token.getUsername(),token.getPswd());
if(null == user){
throw new AccountException("帐号或密码不正确!");
/**
* 如果用户的status为禁用。那么就抛出<code>DisabledAccountException</code>
*/
}else if(UUser._0.equals(user.getStatus())){
throw new DisabledAccountException("帐号已经禁止登录!");
}else{
//更新登录时间 last login time
user.setLastLoginTime(new Date());
userService.updateByPrimaryKeySelective(user);
}
return new SimpleAuthenticationInfo(user,user.getPswd(), getName());
}
/**
* 授权
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
Long userId = TokenManager.getUserId();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//根据用户ID查询角色(role),放入到Authorization里。
Set<String> roles = roleService.findRoleByUserId(userId);
info.setRoles(roles);
//根据用户ID查询权限(permission),放入到Authorization里。
Set<String> permissions = permissionService.findPermissionByUserId(userId);
info.setStringPermissions(permissions);
return info;
}
/**
* 清空当前用户权限信息
*/
public void clearCachedAuthorizationInfo() {
PrincipalCollection principalCollection = SecurityUtils.getSubject().getPrincipals();
SimplePrincipalCollection principals = new SimplePrincipalCollection(
principalCollection, getName());
super.clearCachedAuthorizationInfo(principals);
}
/**
* 指定principalCollection 清除
*/
public void clearCachedAuthorizationInfo(PrincipalCollection principalCollection) {
SimplePrincipalCollection principals = new SimplePrincipalCollection(
principalCollection, getName());
super.clearCachedAuthorizationInfo(principals);
}
}
明天计划的事情:自己开始复盘后台系统的登录设置
遇到的问题:知识量太大
收获:熟悉了新的技术
评论