1.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>
2.配置securityManager
<!-- 1. 配置 SecurityManager! --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="authenticator" ref="authenticator" /> <property name="realms"> <list> <ref bean="shiroRealm"/> </list> </property> </bean>
3.配置Reaml
<!-- 3. 配置 Realm 3.1 直接配置实现了 org.apache.shiro.realm.Realm 接口的 bean --> <bean id="shiroRealm" class="com.gjp.shiroRealms.ShiroRealm"> <property name="credentialsMatcher"> <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"> <!-- 加密方式 --> <property name="hashAlgorithmName" value="MD5" /> <!-- 加密次数 --> <property name="hashIterations" value="1024"/> </bean> </property> </bean>
4.配置 LifecycleBeanPostProcessor,可以自定的来调用配置在 Spring IOC 容器中 shiro bean 的生命周期方法
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
5.启用 IOC 容器中使用 shiro 的注解. 但必须在配置了 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>
6.配置 ShiroFilter.
<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="/list.jsp" /> <property name="unauthorizedUrl" value="/unauthorized.jsp" /> <!-- 配置哪些页面需要受保护. 以及访问这些页面需要的权限. 1). anon 可以被匿名访问 2). authc 必须认证(即登录)后才可能访问的页面. 3). logout 登出. 4). roles 角色过滤器 /shiro/login = anon /shiro/logout = logout /user.jsp = roles[user] /admin.jsp = roles[admin] /** = authc 放在最后面,因为这个filter加载是有先后顺序的,存在覆盖的 如果写在第一行,则后面的所有配置将不起作用 --> <property name="filterChainDefinitions"> <value> /login.jsp = anon /shiro/login = anon /shiro/logout = logout /admin.jsp = roles[admin] /user.jsp = roles[user] /** = authc </value> </property> </bean>
配置Reaml
protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { // 根据用户情况,来构建AuthenticationInfo对象并返回,通常使用的是SimpleAuthenticationInfo SimpleAuthenticationInfo info = null; // 1.把AuthenticationToken转换成UsernamePasswordToken UsernamePasswordToken upToken = (UsernamePasswordToken) token; // 2.从UsernamePasswordToken中 获取username String username = upToken.getUsername(); // 3.调用数据库方法,从数据库中查询username对应用户记录 User user = new User(); user.setUsername(username); user = userService.selectUserByName(user); // 4.若用户不存在则可以抛出AuthenticationException异常 // 此处有个问题,如果用户输入一个不存在的用户,查出来的数据是null // 调用.会报NullPointException异常 if (user.getUsername() == null && user.getUsername() == "") { throw new UnknownAccountException("用户不存在"); } // 5.根据用户信息的情况,决定是否还需要抛出其他异常 // principal:认证的实体信息,可以是username,也可以是bean对象,邮箱等 // Object principal = user.getUsername(); // realmName:当前realm对象的name,调用父类的getName()方法获取即可 // String realmName = getName(); // credentialsSalt: 盐值. ByteSource credentialsSalt = ByteSource.Util.bytes(user.getUsername()); //构建返回对象,将用户名,密码,盐值,当前realm的名称提供给shiro做加密认证 info = new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), credentialsSalt, getName()); return info; }
授权
@Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // 1、从PrincipalCollection中获取登录用户的信息 Object principal = principals.getPrimaryPrincipal(); // 2、从登录用户的信息,来获取当前用户的角色和权限 Set<String> roles = new HashSet<String>(); // 创建用户 User user = new User(); //直接将principal强转成字符串 user.setUsername((String)principal); // 查询当前用户详细信息 user = userService.selectUserByName(user); // 将逗号分隔的角色id切分 String[] rolesIdArr = user.getRolesid().split(","); for (int i = 0; i < rolesIdArr.length; i++) { Roles role = new Roles(); // 因为数据库中user的rolesid存的是以逗号分隔的数据,所以用的字符串存储的 // 所以此处应转换成int role.setId(Integer.valueOf(rolesIdArr[i])); // 查询对应的角色信息 role = rolesService.selectRolesById(role); // 将角色信息存入集合 roles.add(role.getRolename()); } // 3、创建 SimpleAuthorizationInfo,并设置其属性roles属性. SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.setRoles(roles); // 4、返回对象 return info; }