shiro入门
常见的权限控制方式
URL拦截权限控制,底层基于拦截器或者过滤器实现
方法注解权限控制,底层基于代理技术实现,为Action创建代理对象,由代理对象进行权限校验
用户-角色-权限:权限限定了操作,角色是权限的集合,方便权限管理,用户授予了什么角色,拥有其角色的权限集合
apache shiro框架简介
*官网:shiro.apache.org
*下载
*shiro框架的核心功能:
认证
授权
会话管理
加密
*shiro框架认证流程
Application Code:应用程序代码,由开发人员负责开发的
Subject:框架提供的接口,代表当前用户对象
SecurityManager:框架提供的接口,代表安全管理器对象
Realm:可以开发人员编写,框架也提供一些,类似于DAO,用于访问权限数据
*在项目中应用shiro框架进行认证
第一步:引入shiro框架相关的jar
<!-- 引入shiro框架的依赖 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.2.2</version>
</dependency>
第二步:在web.xml中配置spring框架提供的用于整合shiro框架的过滤器
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
第三步:在spring配置文件中配置bean,id为shiroFilter
*这里设置了访问资源所需要的权限,有权限才可以继续执行
<!-- 使用shiro安全认证框架 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 注入安全管理器对象 -->
<property name="securityManager" ref="securityManager"/>
<!-- 注入相关页面访问URL -->
<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
/images/** = anon
/validatecode.jsp* = anon
/login.jsp = anon
/userAction_login.action = anon
/page_base_staff.action = perms["staff-list"]
/* = authc
</value>
</property>
</bean>
框架提供的过滤器
第四步:配置安全管理器 ↑ 引用的注意名字
<!-- 注册安全管理器对象 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="bosRealm"/>
</bean>
第五步:设置认证和授权的类。BOSRealm.java
package com.pb.service.realm;
public class BOSRealm extends AuthorizingRealm{
@Autowired
private IUserDao userDao;
//认证方法
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("自定义的realm中认证方法执行了。。。。");
UsernamePasswordToken passwordToken = (UsernamePasswordToken)token;
//获得页面输入的用户名
String username = passwordToken.getUsername();
//根据用户名查询数据库中的密码
TUser user = userDao.findUserByUsername(username);
if(user == null){
//页面输入的用户名不存在
return null;
}
//简单认证信息对象
AuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), this.getName());
//框架负责比对数据库中的密码和页面输入的密码是否一致
return info;
}
//授权方法
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addStringPermission("staff-list");
//TODO 后期需要去数据库查询权限信息。。
TUser user=(TUser) SecurityUtils.getSubject().getPrincipal();
TUser user2=(TUser) principals.getPrimaryPrincipal();
System.out.println(user==user2);
return info;
}
}
第六步:注册认证授权类 ↑ 引用的注意 id 值
<!-- 注册realm -->
<bean id="bosRealm" class="com.pb.service.realm.BOSRealm"></bean>
第七步:修改我们自定义的方法,进行登录权限认证
public String login(){
//从Session中获取生成的验证码
String validatecode = (String) ServletActionContext.getRequest().getSession().getAttribute("key");
//校验验证码是否输入正确
if(StringUtils.isNotBlank(checkcode) && checkcode.equals(validatecode)){
//输入的验证码正确
//TUser user = userService.login(model);
//if(user != null){
//登录成功,通过安全框架进行认证
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(model.getUsername(),MD5Utils.md5(model.getPassword()));
subject.login(token);
TUser user2 = (TUser) subject.getPrincipal();
//将user对象放入session,跳转到首页
ServletActionContext.getRequest().getSession().setAttribute("loginUser", user2);
return HOME;
//}else{
//登录失败,,设置提示信息,跳转到登录页面
//输入的验证码错误,设置提示信息,跳转到登录页面
//this.addActionError("用户名或者密码输入错误!");
//return LOGIN;
//}
}else{
//输入的验证码错误,设置提示信息,跳转到登录页面
this.addActionError("输入的验证码错误!");
return LOGIN;
}
}
第八步:在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"/>
第九步:在Action的方法上使用shiro注解,设置访问的权限
@RequiresPermissions("staff-list")
public String pageQuery() throws IOException{
staffService.pageQuery(pageBean);
String[] excludes=new String[]{"currentPage","pageSize","detachedCriteria","qpWorkbills","qpNoticebills","qpNoticebills_1","bcDecidedzones","qpWorkbills_1","bcDecidedzones_1"};
javaToJson(pageBean, excludes);
return NONE;
}
第十步:在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"></exception-mapping>
</global-exception-mappings>
第十一步:可以在页面上通过shiro标签来控制页面标签的显示
导入标签库
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
进行显示控制
<shiro:hasPermission name="staff-delete">
{
id : 'button-delete',
text : '作废',
iconCls : 'icon-cancel',
handler : doDelete
},
</shiro:hasPermission>
补充:代码级别的权限控制(基于代理技术实现)没有权限抛没有权限异常然后跳到全局结果异常页面
Subject subject = SecurityUtils.getSubject();
subject.checkPermission("staff-list");