权限管理框架apache shiro的用法
一、权限概述
认证:系统提供的用于识别用户身份的功能,通常登录功能就是认证功能-----让系统知道你是谁??
授权:系统授予用户可以访问哪些功能的许可(证书)----让系统知道你能做什么??
二、常见的权限控制方式
2.1 URL拦截权限控制
底层基于拦截器或者过滤器实现
2.2 方法注解权限控制
底层基于代理技术实现,为Action创建代理对象,由代理对象进行权限校验
三、权限关系数据模型
- 权限表
- 角色表
- 用户表
- 角色权限关系表
- 用户角色关系表
角色就是权限的集合,引入角色表,是为了方便授权
四、Apache shiro框架介绍
- 官网:shiro.apache.org
- 下载文件
- shiro框架的核心功能
认证
授权
会话管理
加密 - shiro框架认证流程
Application Code:应用程序代码,由开发人员负责开发的
Subject:框架提供的接口,代表当前用户对象
SecurityManager:框架提供的接口,代表安全管理器对象
Realm:可以开发人员编写,框架也提供一些,类似于DAO,用于访问权限数据
五、Apache shiro框架的使用
说明:本文介绍的Apache shiro框架的使用是maven项目,采用的开发框架是Struts2、spring、hibernate
5.1 添加shiro框架的依赖
在父工程的pom.xml文件中添加依赖,引入shiro框架相关的包
5.2 在web.xml中配置shiro框架过滤器
在web.xml中配置spring框架提供的用于整合shiro框架的过滤器
注:web.xml中的过滤器的配置,Struts2的过滤器一定要在最后的位置
5.3 在spring配置文件中配置bean,id为shiroFilter
框架提供的过滤器有:
5.4 配置安全管理器
5.5 修改UserAction中的login方法,使用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;
}
}
5.6 自定义realm,并注入给安全管理器
在认证方法中核验用户是否存在,在授权方法中赋予用户对应的权限
public class BOSRealm extends AuthorizingRealm{
@Autowired
private IUserDao userDao;
//认证方法
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("realm中的认证方法执行了。。。。");
UsernamePasswordToken mytoken = (UsernamePasswordToken)token;
String username = mytoken.getUsername();
//根据用户名查询数据库中的密码
User 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) {
// TODO Auto-generated method stub
return null;
}
并且在spring的配置文件中,将自定义的realm注入给安全管理器
六、认证和授权
6.1 认证方法
在认证方法中检验用户是否存在
//认证方法
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
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;
}
6.2 授权方法
在授权方法中赋予用户相应的权限
//授权方法
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//获取当前登录对象
User user = (User) SecurityUtils.getSubject().getPrincipal();
//User user2 = (User) principals.getPrimaryPrincipal();
//根据当前登录用户查询数据库,获取实际对应的权限
List<Function> list = null;
if (user.getUsername().equals("admin")) {
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Function.class);
//超级管理员内置用户,查询所有权限数据
list = functionDao.findByCriteria(detachedCriteria);
}else {
list = functionDao.findFunctionListByUserId(user.getId());
}
for (Function function : list) {
//为用户授权
info.addStringPermission(function.getCode());
}
//TODO 后期需要修改为根据登录用户查询数据库,获取实际对应的权限
return info;
}
七、shiro权限控制
7.1 使用shiro的方法注解方式权限控制
7.1.1 第一步:在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"/>
7.1.2 第二步:在Action的方法上使用shiro注解
7.1.3 第三步:在struts.xml中配置全局异常捕获,当shiro框架抛出权限不足异常时,跳转到权限不足提示页面
7.2 使用shiro提供的页面标签方式权限控制
7.2.1 第一步:在jsp页面中引入shiro的标签库
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
7.2.2 第二步:使用shiro的标签控制页面元素展示
此时,当该用户没有此权限时,页面上按钮将不会展示
八、总结shiro框架提供的权限控制方式
8.1 URL拦截权限控制(基于过滤器实现)
应用于一些基础的页面方法之间的拦截
8.2 方法注解权限控制(基于代理技术实现)
使用简单,最常用
8.3 页面标签权限控制(标签技术实现)
需要配合第二种,才能实现完全程度的拦截
8.4 代码级别权限控制(基于代理技术实现)
不常用