shiro学习记录(二)
1 在项目中应用shiro框架进行认证
第一步:引入shiro框架相关的jar
<!-- 引入shiro框架的依赖 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-all</artifactId> <version>1.2.2</version> </dependency>
第二步:在web.xml中配置spring框架提供的用于整合shiro框架的过滤器(因为是ssh框架,一定要放在structs过滤器前面)
<!-- 配置spring框架提供的用于整合shiro框架的过滤器 --> <filter> <filter-name>shrioFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>shrioFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
启动tomcat服务器,抛出异常:spring工厂中不存在一个名称为“shiroFilter”的bean对象
第三步:在spring配置文件中配置bean,id为shiroFilter
<!-- 配置shiro框架过滤器工厂对象 --> <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="/index.jsp" /> <property name="unauthorizedUrl" value="/unauthorized.jsp" /> <!-- 注入url拦截规则--> <property name="filterChainDefinitions"> <value> /css/** = anon<!-- 匿名,不登录 --> /js/** = anon /image/** = anon /validatecode.jsp* = anon /login.jsp = anon /userAction_login.action = anon /page_base_staff.action = perms["staff-list"]<!-- perms过滤器,可以判断是否存在逻辑staff-list --> /* = authc<!-- 过滤器别名,判断当前用户是否认证 --> </value> </property> </bean>
框架提供的过滤器:
第四步:配置安全管理器
<!-- 注册安全管理器对象 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager" />
第五步:修改UserAction中的login方法,使用shiro提供的方式进行认证操作
/** * 用户登录,使用shiro框架认证登录 */ public String login() { //从session中获取验证码 String validateCode = (String) ServletActionContext.getRequest().getSession().getAttribute("key"); //校验验证码是否输入正确 if (StringUtils.isNotBlank(checkCode) && checkCode.equals(validateCode)) { //使用shiro框架提供的方法进行认证操作 Subject subject = SecurityUtils.getSubject();//获取当前用户对象,状态为"未认证" AuthenticationToken token = new UsernamePasswordToken(model.getUserName(),MD5Utils.md5(model.getPassWord()));//创建用户名密码令牌对象 try{ subject.login(token); } catch(Exception e) { e.printStackTrace(); return LOGIN; } User user = (User) subject.getPrincipal(); ServletActionContext.getRequest().getSession().setAttribute("loginUser", user); return HOME; } else { //输入验证码错误,设置提示信息,跳转到登录页面 this.addActionError("输入验证码错误!"); return LOGIN; } }
第六步:自定义realm,并注入给安全管理器
public class BOSRealm extends AuthorizingRealm { @Autowired private IUserDao userDao; //授权方法 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { return null; } //认证方法 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("自定义的realm中认证方法执行了。。。。"); UsernamePasswordToken passwordToken = (UsernamePasswordToken) token; //获取页面输入的用户名 String username = passwordToken.getUsername(); //根据用户名查询数据库中的密码 User user = userDao.findUserByUserName(username); if (user == null) { //页面输入用户名不存在 return null; } //简单认证信息对象 AuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassWord(), this.getName()); //框架负责比对数据库中的密码和页面输入的密码是否一致 return info; } }
2.在realm中实现授权
在BOSRealm中实现授权
//授权方法 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); //为用户授权 info.addStringPermission("staff-list"); //TODO 后期需要修改为登录用户查询数据库,获取实际对应的权限 return info; }
3.使用shiro的方法注解方式权限控制
第一步: 在spring配置文件中开启shiro注解支持
<!-- 开启shiro注解支持 --> <bean id="defaultAdvisorAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"> <!-- 必须使用cglib方式为action对象创建代理对象 --> <property name="proxyTargetClass" value="true" /> </bean> <!-- 配置shiro框架提供的切面类,用于创建代理对象 --> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"></bean>
第二步:在Action的方法上使用shiro注解
@RequiresPermissions("staff-delete")//执行这个方法,需要当前用户具有staff-delete的权限 public String delBatchStaff() { staffService.delBatchStaff(ids); return LIST; }
第三步:在struts.xml中配置全局异常捕获,当shiro框架抛出权限不足异常时,跳转到权限不足提示页面
<!-- 配置全局结果集 --> <global-results> <result name="login">/login.jsp</result> <result name="unauthorized">/unauthorized.jsp</result> </global-results> <global-exception-mappings> <exception-mapping result="unauthorized" exception="org.apache.shiro.authz.UnauthorizedException" /> </global-exception-mappings>
4.总结shiro框架提供的权限控制方式
(1) URL拦截权限控制(基于过滤器实现)
<!-- 配置shiro框架过滤器工厂对象 --> <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="/index.jsp" /> <property name="unauthorizedUrl" value="/unauthorized.jsp" /> <!-- 注入url拦截规则--> <property name="filterChainDefinitions"> <value> /css/** = anon<!-- 匿名,不登录 --> /js/** = anon /image/** = anon /validatecode.jsp* = anon /login.jsp = anon /userAction_login.action = anon /page_base_staff.action = perms["staff-list"]<!-- perms过滤器,可以判断是否存在逻辑staff-list --> /* = authc<!-- 过滤器别名,判断当前用户是否认证 --> </value> </property> </bean>
(2) 方法注解权限控制(基于代理技术实现)
@RequiresPermissions("staff-delete")//执行这个方法,需要当前用户具有staff-delete的权限 public String delBatchStaff() { staffService.delBatchStaff(ids); return LIST; }
(3) 页面标签权限控制(标签技术实现)
(4)代码级别权限控制(基于代理技术实现)