一.shrio简介
Apache Shiro 是一个强大而灵活的开源安全框架,它干净利落地处理身份认证,授权,企业会话管理和加密。
shiro主要能做的事:
1. 验证用户来核实他们的身份2. 对用户执行访问控制, 如: 判断用户是否被分配了一个确定的安全角色 判断用户是否被允许做某事3. 在任何环境下使用 Session API,即使没有 Web 或 EJB 容器。4. 在身份验证,访问控制期间或在会话的生命周期,对事件作出反应。5. 聚集一个或多个用户安全数据的数据源,并作为一个单一的复合用户“视图”。6. 启用单点登录(SSO)功能。7. 为没有关联到登录的用户启用"Remember Me"服务
二.Shiro 的架构的3 个主要概念:Subject,SecurityManager 和 Realms
Subject:简单理解为当前登录的用户或者正在与应用程序交互的东西
SecurityManager:整个shiro框架的核心,用来管理协调繁重的操作,包括认证,授权,与数据库交互,session管理,缓存管理等等
Realms::Realms 担当 Shiro 和应用程序的安全数据之间的“桥梁”或“连接器,开发人员通常需要编写自己的realm类来进行自己的认证与授权,通常需要与数据库交互.
三.Shiro与Spring的整合使用
1.在web.xml中配置shrioFilter拦截器
<filter-name>ShiroFilter</filter-name> <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class> </filter>
<filter>
<filter-mapping>
<filter-name>ShiroFilter</filter-name>
<url-pattern>*/</url-pattern>
</filter-mapping>
2.创建自己的MyRealm类
public class MyRealm extends AuthorizingRealm {
@Resource
private IUserDao iUserDaoImpl;
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
// 用户登录的认证
UsernamePasswordToken atoken = (UsernamePasswordToken) token;
String username = atoken.getUsername();
User user = iUserDaoImpl.findByUsername(username);
if (user == null) {
return null;
} else {
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,
user.getPassword(), this.getClass().getName());
return info;
}
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principal) {
//用户授权
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
User user = (User) principal.getPrimaryPrincipal();
List<AuthFunction> list =null;
if(user.getUsername().equals("admin")){
//查出所有权限
list= iUserDaoImpl.findAllFunctions();
}else {
//根据用户id查出对应权限
list = iUserDaoImpl.findFunctionsById(user.getId());
}
// 授权
if(list!=null){
for (AuthFunction authFunction : list) {
info.addStringPermission(authFunction.getCode());
}
}
return info;
}
}
2.配置Spring
<!-- shrio开发bean配置 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login.jsp" />
<property name="successUrl" value="/home.jsp" />
<property name="unauthorizedUrl" value="/unauthorized.jsp" />
<property name="filterChainDefinitions">
<value>
/css/**=anon
/images/**=anon
/js/**=anon
/validatecode.jsp=anon
/login.jsp=anon
/userAction_login.action=anon
/page_base_staff.action=perms["staff"]
/**=anon
</value>
</property>
</bean>
<!-- shiro安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm"></property>
<property name="cacheManager" ref="cacheManager"></property>
</bean>
<bean id="myRealm" class="com.wuhan.bos.shiro.MyRealm" />
<bean id ="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManagerConfigFile" value="classpath:ehcache.xml"></property>
</bean>
<!-- shiro注解开发,cglib动态代理 -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
<property name="proxyTargetClass" value="true"></property>
</bean>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
</bean>
4.提供
ehcache
缓存策略的配置文件ehcache.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
maxElementsOnDisk="10000000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
/>
</ehcache>
四.shiro的注解开发
shiro框架整合到Spring后,可以使用注解开发,即通过在资源上提供注解来控制用户的访问权限,提高权限控制的细度,可以和配置文件结合使用
常见的主要有以下几种:
@RequiresAuthentication:验证用户是否登录,等同于方法subject.isAuthenticated() 结果为true时,即登录后可访问
@ RequiresUser:验证用户是否被记忆,user有两种含义:
一种是成功登录的(subject.isAuthenticated() 结果为
true);
另外一种是被记忆的( subject.isRemembered()结果为true)。
@ RequiresGuest:验证是否是一个guest(游客)的请求,与@ RequiresUser完全相反。
换言之,RequiresUser ==
!RequiresGuest 。
此时subject.getPrincipal() 结果为null.
@ RequiresRoles
例如:@RequiresRoles("aRoleName");
void someMethod();
如果subject中有aRoleName角色才可以访问方法someMethod。如果没有这个权限则会抛出异常AuthorizationException。
@RequiresPermissions
例如: @RequiresPermissions( {"file:read", "write:aFile.txt"} )
void someMethod();
要求subject中必须同时含有file:read和write:aFile.txt的权限才能执行方法someMethod()。否则抛出异常AuthorizationException。
五.shiro框架提供的标签
标签名称
标签条件(均是显示标签内容)
<shiro:authenticated>
登录之后
<shiro:notAuthenticated>
不在登录状态时
<shiro:guest>
用户在没有RememberMe时
<shiro:user>
用户在RememberMe时
<shiro:hasAnyRoles name="abc,123" >
在有abc或者123角色时
<shiro:hasRole name="abc">
拥有角色abc
<shiro:lacksRole name="abc"> 没有角色abc
<shiro:hasPermission name="abc">
拥有权限资源abc
<shiro:lacksPermission name="abc">
没有abc权限资源
<shiro:principal>
默认显示用户名称