shiro集成Spring
需要有Spring的环境 ssj/项目
3.1 导包
因为spring集成类shrio框架,所以导shiro和spring的集成包,如果要测试还是导上测试包,我这没导测试包
<!-- shiro(权限框架)的支持包 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-all</artifactId> <version>1.4.0</version> <type>pom</type> </dependency> <!-- shiro与Spring的集成包 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency>
3.2 web.xml
中配置代理过滤器
<!-- shiro的过滤器(帮我们拦截请求)-》什么事情都不做 Delegating:授(权); 把(工作、权力等)委托(给下级); 选派(某人做某事) Proxy:代理 -> 需要通过名称(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>
3.3 准备自定义Realm
public class MyRealm extends AuthorizingRealm { //授权认证功能就写在这里面 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { //获取授权对象 SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); //从getRoles()方法中获取角色并放且放到授权对象中,getRoles()方法在下面 Set<String> roles = getRoles(); authorizationInfo.setRoles(roles); //从getPerms()方法中获取权限并放且放到授权对象中,getPerms()方法在下面 Set<String> perms = getPerms(); authorizationInfo.setStringPermissions(perms); return authorizationInfo; } /** * 假设这里获取到当前用户的角色 */ private Set<String> getRoles(){ Set<String> roles = new HashSet<>(); roles.add("admin"); roles.add("it"); return roles; } /** * 假设这里获取到当前用户的权限 */ private Set<String> getPerms(){ Set<String> perms = new HashSet<>(); perms.add("employee:index"); return perms; } /** * 记住:如果这个方法返回null,就代表是用户名错误,shiro就会抛出:UnknownAccountException */ //身份认证(登录)就写在这里面 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //1.拿到令牌(UsernamePasswordToken) UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken; //2.拿到用户名,判断这个用户是否存在 // 2.1 拿到传过来的用户名 String username = token.getUsername(); // 2.2 根据用户名从getUsers()方法中拿到密码,getUsers()方法在下面 String password = this.getUsers(username); // 2.3 如果没有拿到密码(没有通过用户名拿到相应的用户->用户不存在) if(password==null){ return null; } //记住:我们只在正常完成这里的功能,shiro会判断密码是否正确 //3.返回 AuthenticationInfo这个对象 /** * 咱们创建对象需要传的参数:SimpleAuthenticatinInof(4个参数顺序解释) * Object principal:主体(可以乱写) -> 登录成功后,你想把哪一个对象存下来 * Object credentials:凭证(就是密码) -> 数据库中的密码 * credentials(密码)Salt:盐值 * String realmName : realm的名称(可以乱写) */ //拿到咱们的盐值对象(ByteSource) ByteSource salt = ByteSource.Util.bytes("itsource"); SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username,password,salt,"myRealm"); return authenticationInfo; } /** * 假设这里是根据用户名进行的查询 * MD5:e10adc3949ba59abbe56e057f20f883e * MD5+10次:4a95737b032e98a50c056c41f2fa9ec6 * MD5+10次+itsource:831d092d59f6e305ebcfa77e05135eac */ public String getUsers(String username){ if("admin".equals(username)){ return "831d092d59f6e305ebcfa77e05135eac"; }else if("zhang".equals(username)){ return "123"; } return null; } }
3.4准备工厂返回权限
- 返回的Map值是有顺序的
- 修改后要重启(热启动无效)
/** * 用于返回下面的这些值(这里的值是有顺序的:LinkedHashMap) * <value> /login = anon /s/permission.jsp = perms[user:index] /** = authc </value> 这里修改后要重新启动tomcat */ public class ShiroFilterMapFactory { public Map<String,String> createMap(){ Map<String,String> map = new LinkedHashMap<>(); //anon:需要放行的路径 map.put("/login","anon"); //perms:权限拦截 map.put("/s/permission.jsp","perms[employee:index]"); //authc:拦截 map.put("/**","authc"); return map; } }
3.5 applicationContext-shiro.xml
的配置
- 先在
applicationContext.xml
中引入它<import resource="classpath:applicationContext-shiro.xml" />
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <!-- Shiro的核心对象(权限管理器) DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(jpaRealm) --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="jpaRealm"/> </bean> <!-- JpaRealm jpaRealm = new JpaRealm(); 配置咱们的自定义realm --> <bean id="jpaRealm" class="cn.itsource.aisell.web.shiro.JpaRealm"> <!--Realm的名称--> <property name="name" value="jpaRealm"/> <property name="credentialsMatcher"> <!-- 配置哈希密码匹配器 --> <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"> <!--加密方式:MD5--> <property name="hashAlgorithmName" value="MD5"/> <!--迭代次数--> <property name="hashIterations" value="10" /> </bean> </property> </bean> <!-- 这三个配置好,可以支持注解权限 --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"/> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager"/> </bean> <!-- shiro真正的过滤器(功能就是它完成的) 这个bean的名称必需和web.xml里的的代理过滤器名字相同 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!--必需要用到权限管理器--> <property name="securityManager" ref="securityManager"/> <!--如果你没有登录,你会进入这个页面--> <property name="loginUrl" value="/s/login.jsp"/> <!--登录成功后,进入的页面(一般没什么用)--> <property name="successUrl" value="/s/main.jsp"/> <!--如果你没有权限,你会进入这个页面--> <property name="unauthorizedUrl" value="/s/unauthorized.jsp"/> <!-- 过滤描述 anon:不需要登录也可以访问 authc:登录与权限的拦截 perms:如果你有user:index的权限,你就可以访问:/s/permission.jsp --> <!-- <property name="filterChainDefinitions"> <value> /login = anon /s/permission.jsp = perms[user:index] /** = authc </value> </property> --> <property name="filterChainDefinitionMap" ref="filterChainDefinitionMap" /> </bean> <!-- 以前在四个创建Bean的方法中讲过 ShiroFilterMapFactory shiroFilterMapFactory = new shiroFilterMapFactory(); Map filterChainDefinitionMap=shiroFilterMapFactory.createMap(); --> <!--拿到shiroFilterMapFactory里面的createMap方法的值 --> <bean id="filterChainDefinitionMap" factory-bean="shiroFilterMapFactory" factory-method="createMap" /> <!--配置返回shiro权限拦截的bean--> <bean id="shiroFilterMapFactory" class="cn.itsource.aisell.web.shiro.ShiroFilterMapFactory"/> </beans>