SSM整合shiro相关配置
SSM整合shiro相关配置
- 首先要在pom.xml文件中添加shiro相关依赖shiro-all,这个依赖包含了shiro-web,shiro-core,shiro-spring,shiro-ehcache…等一系列jar包,所以这里只用添加这一个依赖就够了
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.2.2</version>
</dependency>
一般shiro都会用到ehcache缓存还需要添加ehcache依赖
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.6.8</version>
</dependency>
- 配置web.xml,shiro核心过滤器,所有的请求都会在这里被拦截,这里的一定要和下面spring-shiro.xml配置文件中的过滤器名字保持一致
<!-- 这里需要加载spring-shiro.xml配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mybatis.xml,classpath:spring-shiro.xml</param-value>
</context-param>
...
<!-- shiro过虑器,DelegatingFilterProxy会从spring容器中找shiroFilter -->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- spring-shiro.xml相关配置,shiro的核心配置文件
<!-- 1.凭证匹配器 -->
<!-- 这里的凭证指的是对登录用户的密码进行md5加密,hashIterations是散列加密次数,可以是任意次数,但每次加密的时候一定要保持一致 -->
<bean id="credentialsMatcher"
class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="md5" />
<property name="hashIterations" value="1024" />
</bean>
<!-- 2.Realm实现 -->
<!-- 自定义Realm,自己写一个Java类,继承AuthorizingRealm,重写父类的两个方法,具体Realm的写法下面有详细介绍,class指定Realm类的全路径,引入上面的凭证匹配器 -->
<bean id="saipoteRealm" class="com.zc.shiro.ShiroRealm">
<property name="credentialsMatcher" ref="credentialsMatcher" />
</bean>
<!-- 3.配置ehcache缓存 -->
<!-- 当用户登入之后访问特定的页面时就会去数据库查询该用户的角色权限,如果没有配置缓存的话,第二次访问又要向数据库发送查询,增加了数据库的压力,如果配置了缓存,就会把角色权限放到缓存之中,不需要多次去数据库查询 -->
<bean id="ehCacheManager"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:shiro-ehcache.xml" />
<property name="shared" value="true"></property>
</bean>
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManager" ref="ehCacheManager" />
</bean>
<!-- 4.安全管理器securityManager -->
<!-- 引入Realm,引入缓存 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="saipoteRealm" />
<property name="cacheManager" ref="cacheManager" />
</bean>
<!-- 5.Shiro生命周期处理器 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<!-- 6.开启shiro注解模式 -->
<!-- 如果使用注解模式,必须采用cglib针对类进行代理 -->
<bean
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor">
<property name="proxyTargetClass" value="true" />
</bean>
<bean
class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
<!-- 7. 自定义LogoutFilter,用户退出登录功能 -->
<bean id="logoutFilter" class="org.apache.shiro.web.filter.authc.LogoutFilter">
<property name="redirectUrl" value="/login.jsp" />
</bean>
<!-- 8. 定义需要特殊处理的异常,用类名或完全路径名作为key,异常页名作为值 -->
<!--shiro权限异常处理-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<!-- 未认证 -->
<prop key="org.apache.shiro.authz.UnauthenticatedException">/login.jsp</prop>
<!-- 未授权 -->
<prop key="org.apache.shiro.authz.UnauthorizedException">/unauthorized.jsp</prop>
</props>
</property>
<!-- 9. 配置shiroFilter,这里的shiroFilter要和web.xml配置的名字保持一致 -->
<!-- 下面几个需要跳转的页面需要自己新建 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- Shiro的核心安全接口,这个属性是必须的 -->
<property name="securityManager" ref="securityManager" />
<!-- 要求登录时的链接(登录页面地址),非必须的属性,默认会自动寻找Web工程根目录下的"/login.jsp"页面 -->
<property name="loginUrl" value="/login.jsp" />
<!-- 登录成功后要跳转的连接 -->
<property name="successUrl" value="/index.jsp"></property>
<!-- 用户访问未对其授权的资源时,所显示的连接 -->
<property name="unauthorizedUrl" value="/unauthorized.jsp"></property>
<!-- 过虑器链定义,从上向下顺序执行,一般将/**放在最下边 -->
<property name="filters">
<map>
<entry key="logout" value-ref="logoutFilter" />
</map>
</property>
<property name="filterChainDefinitions">
<value>
<!-- anon不需要认证 -->
<!-- 对于一些静态资源不需要认证就可以直接访问,否则会出现页面某些样式,js,图片加载不出来 -->
<!-- /logout = logout就是用户退出登录功能,在页面只需要写超链接href="logout"就可以了,下面左边的louout要和上面的<map>标签里的key保持一致 -->
/login.jsp= anon
/logout = logout
/css/** = anon
/images/** = anon
/js/** = anon
/user/login = anon
<!-- authc需要认证 -->
/** = authc
</value>
</property>
</bean>
shiro的配置远不止如此,详情可以查看shiro官方文档
4. 配置shiro-ehcache.xml
<!-- 这里就用默认配置就行了,如有兴趣可以自己了解 -->
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<defaultCache
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>
贴上部分ehCache配置
name:缓存名称。
maxElementsInMemory:缓存最大个数。
eternal:对象是否永久有效,一但设置了,timeout将不起作用。
timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。
diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
maxElementsOnDisk:硬盘最大缓存个数。
diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
clearOnFlush:内存数量最大时是否清除。
- 自定义Realm
public class ShiroRealm extends AuthorizingRealm {
@Autowired
private UserService userServiceImpl;
@Autowired
private RoleService roleServiceImpl;
@Autowired
private PermissionService permissionServiceImpl;
// 认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
String username = (String) token.getPrincipal();
User user = userServiceImpl.findByUsername(username);
if (user == null) {
throw new UnknownAccountException("未找到用户");// 没找到帐号
}
ByteSource credentialsSalt = ByteSource.Util.bytes(username);
// 交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
user, // 用户
user.getPassword(), // 密码
credentialsSalt, getName() // realm name
);
return authenticationInfo;
}
// 授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principalCollection) {
User user = (User) principalCollection.getPrimaryPrincipal();
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
// 调用业务层,查询角色
List<Role> roles = roleServiceImpl.findRoleByUserId(user.getUserId());
for (Role role : roles) {
authorizationInfo.addRole(role.getRoleName());
}
// 调用业务层,查询权限
List<Permission> permissions = permissionServiceImpl.findByUserId(user
.getUserId());
for (Permission permission : permissions) {
authorizationInfo.addStringPermission(permission
.getPermissionName());
}
return authorizationInfo;
}
// 清除缓存
public void clearCached() {
// 获取当前等的用户凭证,然后清除
PrincipalCollection principals = SecurityUtils.getSubject()
.getPrincipals();
super.clearCache(principals);
}
}
- Controller层登录实现
@RequestMapping("/login")
public Stringlogin(@RequestBody User user) throws Exception{
Subject subject = SecurityUtils.getSubject();// 获取一个用户对象
AuthenticationToken token = new UsernamePasswordToken(user.getUsername(),user.getPassword());// 将用户名和密码传入login方法中//
subject.login(token);// 调用框架自带的login方法
try {
subject .login(token);
} catch (UnknownAccountException e) {
// 用户名未知...
e.printStackTrace();
return "login.jsp";
} catch (IncorrectCredentialsException e) {
// 凭据不正确,例如密码不正确 ...
e.printStackTrace();
lreturn "login.jsp";
} catch (LockedAccountException e) {
// 用户被锁定,例如管理员把某个用户禁用...
e.printStackTrace();
return "login.jsp";
} catch (ExcessiveAttemptsException e) {
// 尝试认证次数多余系统指定次数 ...
e.printStackTrace();
return "login.jsp";
} catch (AuthenticationException e) {
// 其他未指定异常
e.printStackTrace();
return "login.jsp";
}
return "index.jsp";
}
上一篇: 关于shiro动态刷新缓存
下一篇: Shiro框架