shiro:web配置
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:spring-shiro.xml
</param-value>
</context-param>
加载shiro配置文件
<!-- shiro filter的名字是shiroFilter,那么在spring的配置文件中要有一个名字为shiroFilter的bean -->
<filter>
<!-- 这里的filter-name 要和spring 的applicationContext-shiro.xml 里的
org.apache.shiro.spring.web.ShiroFilterFactoryBean 的bean name 相同 -->
<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>
<init-param>
<param-name>targetBeanName</param-name>
<param-value>shiroFilter</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
这里的shiroFilter对应着spring-shiro配置文件中的shiroFilter,/*表示shiro将过滤全部路径
spring-shiro.xml配置
<!-- wbe.xml中shirofilter对应的bean -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login.action" />
<property name="successUrl" value="/query.action" />
<!-- 制定拒绝访问页面 -->
<property name="unauthorizedUrl" value="/error.jsp" />
<!-- 自定义filter配置 -->
<property name="filters">
<map>
<!-- 将自定义 的FormAuthenticationFilter注入shiroFilter中 -->
<entry key="authc" value-ref="formAuthenticationFilter" />
</map>
</property>
<property name="filterChainDefinitions">
<value>
<!-- 请求这个地址自动退出 -->
/logout.action = logout
<!-- 所有url可以匿名访问 -->
/login.jsp = anon
<!-- 查询权限 -->
<!-- /query.action = perms[user:query] /add.action = perms[user:add]
/update.action = perms[user:update] -->
<!-- 所有url都需要认证才可以访问 -->
/** = authc
</value>
</property>
</bean>
securityManager:安全管理器
loginUrl这个value就是shiro所指定的登录界面,successUrl指定登录成功界面,如果不配置登录成功将默认跳转到上次请求路径,unauthorizedUrl这个是一个没有权限路径,当没有权限就会到这个界面,
filters:这个是一个自定义的filter,也就是自定义的过滤方式,上面写的是一个表单过滤器,表单过滤器一般载登录的时候使用
filterChainDefinitions:shiro过滤器链。这个链是从上向下走的基本的有login,logout,anon,authc
安全管理器securityManager
<!-- securityManager安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="userRealm"></property>
<!-- 缓存管理器 -->
<property name="cacheManager" ref="cacheManager"></property>
<!-- session会话管理器 -->
<property name="sessionManager" ref="sessionManager"></property>
<!-- 记住我 -->
<property name="rememberMeManager" ref="rememberMeManager"></property>
</bean>
realm域:realm添加到securityManager,realm相当于数据源,从数据库获取数据,交给securtyManager来认证,授权
cacheManager缓存管理器:每当系统需要访问需要权限的资源的时候,都需要securityMananger从新去获取,这个大大降低的效率,所以可以配置缓存管理器,降低资源消耗。
sessionManager会话管理器:一次登录就是一次会话,如果一个用户一直登录账号,而忘记退出了,这个账户就会一直存在(如果不关闭浏览器),这里我们就需要会话管理器,可以设置生命周期。
rememberManager:从字面上理解就是记住密码
realm
<!-- realm -->
<bean id="userRealm" class="com.my.shiro.realm.userRealm">
<!-- 将凭证匹配器设置到realm中,realm按照凭证匹配器的要求进行散列 -->
<property name="credentialsMatcher" ref="credentialsMatcher" />
</bean>
realm:需要自己写一个类,继承AuthorizingRealm
credentialsMatcher:认证的方式,一般数据库存密码不会存明文,一般都是加密的,所以认证的时候也需要加密认证,这个就是一种认证方式
package com.my.shiro.realm;
import java.util.ArrayList;
import java.util.List;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
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 com.my.shiro.Entity.User;
import com.my.shiro.Service.Impl.userServiceImpl;;
public class userRealm extends AuthorizingRealm{
@Autowired
private userServiceImpl userService;
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
//从principals获取主身份信息
User user = (User) principals.getPrimaryPrincipal();
//根据身份信息获取权限信息
//模拟链接数据库
//System.out.println("11111"+user);
List<String> permissions = new ArrayList<String>();
String permission = "";
permission = userService.findpermission(user.getUsername());
if(permission != null&&!permission.equals("")){
String a[] = permission.split(",");
for(int i = 0; i < a.length; i++){
permissions.add(a[i]);
}
}
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
simpleAuthorizationInfo.addStringPermissions(permissions);
return simpleAuthorizationInfo;
}
//设置realm名称
@Override
public void setName(String name) {
super.setName("testrealm");
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
//first从token(用户输入)中获取用户信息
String usercode = (String) token.getPrincipal();
//根据usercode从数据看中查询
//模拟数据库
String password = userService.findpassword(usercode);
//盐
String salt = "aa";
User u1 = new User();
u1.setPassword(password);
u1.setUsername(usercode);
SimpleAuthenticationInfo simpleAuthenticationInfo = new
SimpleAuthenticationInfo(u1, password, ByteSource.Util.bytes(salt), this.getName());
return simpleAuthenticationInfo;
}
public void clearCached(){
PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
super.clearCache(principals);
}
}
这里面有三个继承父类方法,doGetAuthorizationInfo,doGetAuthenticationInfo,setName
doGetAuthorizationInfo:授权,将已经认证过的人用户分配权限,返回一个授权信息
doGetAuthenticationInfo:认证,用户登录的时候需要认证,返回一个凭证信息
setName:realm名字
credentialsMatcher凭证匹配器
<!-- 凭证匹配器 -->
<bean id="credentialsMatcher"
class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="md5" />
<property name="hashIterations" value="1" />
</bean>
hashAlgorithmName:这个使用的匹配方式就md5,就是加密之后在和数据库数据进行比较
hashIterations:加密迭代次数,1代码加密迭代1次
cacheManager缓存管理器
<!-- 缓存管理器 -->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManagerConfigFile" value="classpath:shiro-ehcache.xml" />
</bean>
这里需要加载一个配置文件shiro-ehcache.xml
<?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">
<!--diskStore:缓存数据持久化的目录 地址 -->
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="1000"
maxElementsOnDisk="10000000"
eternal="false"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>
sessionManager会话管理器
<!-- 会话管理器 -->
<bean id="sessionManager"
class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<!-- session的失效时长,单位毫秒 -->
<property name="globalSessionTimeout" value="600000" />
<!-- 删除失效的session -->
<property name="deleteInvalidSessions" value="true" />
</bean>
globalSessionTimeout:session保存时间
deleteInvalidSessions:失效的session是否删除
formAuthenticationFilter表单过滤器
<bean id="formAuthenticationFilter" class="com.my.shiro.realm.FormAuthentication">
<!-- 表单中账号的input名称 -->
<property name="usernameParam" value="username" />
<!-- 表单中密码的input名称 -->
<property name="passwordParam" value="password" />
<!-- 记住我input的名称 -->
<property name="rememberMeParam" value="rememberMe" />
</bean>
usernameParam,passwordParam,rememberMeParam对应的就是html表单提交input标签的name属性
<form action="/shiro/login.action" method="post"><br>
账号:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="checkbox" name="rememberMe">自动登录<br>
<input type="submit" value="提交">
</form>
登录的时候一般会自动进行表单验证,但是shiro提供的表单验证不能验证验证码之类的,所以需要自己实现FormAuthenticationFilter重写onAccessDenied,在里面可以进行验证码的验证
package com.my.shiro.realm;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
public class FormAuthentication extends FormAuthenticationFilter{
//认证方法
//可以进行验证码校验
@Override
protected boolean onAccessDenied(ServletRequest request,
ServletResponse response) throws Exception {
System.out.println(111);
return super.onAccessDenied(request, response);
}
}
rememberMeManager记住我
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
<property name="cookie" ref="rememberMeCookie"></property>
</bean>
<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<!-- cookie的名字 -->
<constructor-arg value="rememberMe" />
<property name="httpOnly" value="true" />
<property name="maxAge" value="2592000" /><!-- 30天 -->
</bean>
这里主要配置cookie名字,和cookie存活时间,可以就密码可以保存多久不登陆。
shiro生命周期
<!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
把shrio生命周期交给spring管理
shiro注解支持
<!-- 开启aop,对类代理 -->
<aop:config proxy-target-class="true"/>
<!-- 开启shiro注解支持 -->
<bean class=" org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean>
由于shiro是基于aop的所以首先要开启aop支持,在使用org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor开启注解支持
注意这个是写在springmvc.xml中的。