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;
}