Apache Shiro入门.docx
- 文档编号:6007588
- 上传时间:2023-01-02
- 格式:DOCX
- 页数:13
- 大小:143.75KB
Apache Shiro入门.docx
《Apache Shiro入门.docx》由会员分享,可在线阅读,更多相关《Apache Shiro入门.docx(13页珍藏版)》请在冰豆网上搜索。
ApacheShiro入门
ApacheShiro入门
ApacheShiro基本概念
使用Shiro能做什么
验证用户(认证)。
对用户执行访问控制,像是:
判断用户是否具有某一角色。
判断用户是否具有做某事的权限。
在任何环境下都能使用SessionAPI,即使没有诸如Spring,EJB这样的容器。
在授权,访问控制或者会话生命周期中,都能响应事件。
可以使用多个数据源。
支持单点登录(SSO)功能。
支持”RememberMe”服务。
Shiro的特性
从上图可以看出,shiro有4个主要特性,分别是认证(Authentication)、授权(Authorization)、会话管理(SessionManagement)和密码(Cryptography)服务。
以及6个附加(支持)特性,分别是Web支持(WebSupport)、缓存(Caching)、并发(Concurrency)、测试(Testing)支持、以…运行(RunAs)、记住我(RememberMe)。
参照开涛的解释,如下:
Authentication:
身份认证/登录,验证用户是不是拥有相应的身份;
Authorization:
授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:
验证某个用户是否拥有某个角色。
或者细粒度的验证某个用户对某个资源是否具有某个权限;
SessionManager:
会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境的,也可以是如Web环境的;
Cryptography:
加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;
WebSupport:
Web支持,可以非常容易的集成到Web环境;
Caching:
缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率;
Concurrency:
shiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;
Testing:
提供测试支持;
RunAs:
允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;
RememberMe:
记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。
Shiro框架的调用流程
Shiro框架有三个核心组件,分别是:
Subject,SecurityManager和Realms.
Subject:
即“当前操作用户”。
但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(DaemonAccount)或其他类似事物。
它仅仅意味着“当前跟软件交互的东西”。
但考虑到大多数目的和用途,你可以把它认为是Shiro的“用户”概念。
Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。
SecurityManager:
它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。
Realm:
Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。
也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。
从这个意义上讲,Realm实质上是一个安全相关的DAO:
它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。
当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。
配置多个Realm是可以的,但是至少需要一个。
Shiro内置了可以连接大量安全数据源(又名目录)的Realm,如LDAP、关系数据库(JDBC)、类似INI的文本配置资源以及属性文件等。
如果缺省的Realm不能满足需求,你还可以插入代表自定义数据源的自己的Realm实现。
Shiro框架
快速入门案例
引入Maven依赖
--引入shiro框架的依赖-->
在web.xml中配置spring框架提供的过滤器,用于整合shiro框架
--配置Spring整合shiro框架的过滤器,过滤器必须配置在Struts2核心过滤器上面-->
在Spring配置文件中配置bean
配置安全管理器对象(shiro框架最核心的对象)
--配置安全管理器对象-->
配置Shiro提供的一个工厂对象,用于产生过滤器对象
--配置Shiro提供的一个工厂对象,用于产生过滤器对象-->
--配置相关URL-->
--配置登录URL-->
--配置登录成功URL-->
--配置未授权URL-->
--配置URL拦截规则-->
/css/**=anon
/js/**=anon
/images/**=anon
/login.jsp*=anon
/userAction_login*=anon
/manager*=perms["manager"]
/*=authc
PS:
Bean的ID要和过滤器中名称一致,因为过滤器在初始化时,就会加载与其名称一致的Bean。
自定义一个Realm类
packagecom.service.realm;
importjava.util.List;
importjavax.annotation.Resource;
importorg.apache.shiro.authc.AuthenticationException;
importorg.apache.shiro.authc.AuthenticationInfo;
importorg.apache.shiro.authc.AuthenticationToken;
importorg.apache.shiro.authc.SimpleAuthenticationInfo;
importorg.apache.shiro.authc.UsernamePasswordToken;
importorg.apache.shiro.authz.AuthorizationInfo;
importorg.apache.shiro.authz.SimpleAuthorizationInfo;
importorg.apache.shiro.realm.AuthorizingRealm;
importorg.apache.shiro.subject.PrincipalCollection;
importorg.hibernate.criterion.DetachedCriteria;
importorg.hibernate.criterion.Restrictions;
importcom.dao.FunctionDao;
importcom.dao.UserDao;
importcom.domain.Function;
importcom.domain.User;
/**
*用户Realm
*
*@authorSwitch
*@data2016年12月26日
*@versionV1.0
*/
publicclassUserRealmextendsAuthorizingRealm{
//注入用户Dao对象
@Resource(name="userDao")
privateUserDaouserDao;
//注入权限Dao对象
@Resource(name="functionDao")
privateFunctionDaofunctionDao;
//授予权限
@Override
protectedAuthorizationInfodoGetAuthorizationInfo(PrincipalCollectionprincipals){
//创建简单授权对象
SimpleAuthorizationInfoinfo=newSimpleAuthorizationInfo();
//为用户授权
//权限列表
List
//获取当前用户
Useruser=(User)principals.getPrimaryPrincipal();
if("admin".equals(user.getUsername())){
//超级管理员,获取所有权限
functions=functionDao.findAll();
}else{
//普通用户,通过用户id获取其对应的权限
functions=functionDao.findByUserId(user.getId());
}
if(functions!
=null&&functions.size()>0){
for(Functionfunction:
functions){
//添加许可
info.addStringPermission(function.getCode());
}
}
returninfo;
}
//权限认证
@Override
protectedAuthenticationInfodoGetAuthenticationInfo(AuthenticationTokentoken)throwsAuthenticationException{
//强转为子类,用户名密码token,获取Subject传递过来的数据
UsernamePasswordTokenuserToken=(UsernamePasswordToken)token;
//获取用户名
Stringusername=userToken.getUsername();
//在数据库中查询客户
DetachedCriteriadetachedCriteria=DetachedCriteria.forClass(User.class);
detachedCriteria.add(Restrictions.eq("username",username));
List
if(userList!
=null&&userList.size()>0){
Useruser=userList.get(0);
//获取密码
Stringpassword=user.getPassword();
//简单认证信息对象,由SecurityManager负责对比密码数据
//参数1:
Objectprincipal————一般是认证对象,在这里就是用户对象
//参数2:
Objectcredentials————证书,也就是负责校验认证的对象
//参数3:
StringrealmName————realm的名字,随意,但必须唯一
AuthenticationInfoinfo=newSimpleAuthenticationInfo(user,password,this.getName());
returninfo;
}
returnnull;
}
}
将该Realm配置到安全管理器中
--配置用户RealmBean-->
--配置安全管理器对象-->
--管理Realm-->
写一个登录方法
publicStringlogin()throwsException{
//获取session中的验证码
StringloginCheckCode=(String)ActionContext.getContext().getSession().get("loginCheckCode");
if(StringUtils.isBlank(checkcode)||!
loginCheckCode.equals(checkcode)){
this.addActionError("验证码错误");
returnLOGIN;
}
//Shiro认证
//获取subject,代表当前用户对象,状态为:
未认证
Subjectsubject=SecurityUtils.getSubject();
AuthenticationTokentoken=newUsernamePasswordToken(model.getUsername(),MD5Utils.md5(model.getPassword()));
try{
//验证
subject.login(token);
//从本地线程中获取SimpleAuthenticationInfo放入的对象
UserloginUser=(User)subject.getPrincipal();
//加入Session
ActionContext.getContext().getSession().put("loginUser",loginUser);
returnHOME;
}catch(Eptione){
e.printStackTrace();
this.addActionError("用户名或密码错误!
");
returnLOGIN;
}
}
补充:
默认拦截器
Shiro内置了很多默认的拦截器,比如身份验证、授权等相关的。
默认拦截器可以参考org.apache.shiro.web.filter.mgt.DefaultFilter中的枚举拦截器:
noSessionCreationorg.apache.shiro.web.filter.session.NoSessionCreationFilter不创建会话拦截器,调用subject.getSession(false)不会有什么问题,但是如果subject.getSession(true)将抛出DisabledSessionException异常;
PS:
在配置URL拦截规则的时候,使用了很多默认拦截器。
权限控制的四种方式
在了解权限控制之前,先模拟下授权操作,授予manager的权限。
//授予权限
@Override
protectedAuthorizationInfodoGetAuthorizationInfo(PrincipalCollectionprincipals){
//创建简单授权对象
SimpleAuthorizationInfoinfo=newSimpleAuthorizationInfo();
//为用户授权
//TODO:
这里只是模拟授权,一般还需要到数据库中认证
info.addStringPermission("manager");
returninfo;
}
基于URL的权限控制
--配置URL拦截规则-->
/css/**=anon
/js/**=anon
/images/**=anon
/login.jsp*=anon
/userAction_login*=anon
/manager*=perms["manager:
*"]
/*=authc
基于注解的权限控制
在Spring配置文件中启动注解支持
configproxy-target-class="true"/> --自动代理--> --强制使用cglib进行代理--> --配置注解方式权限控制的切面类--> 在Action的方法上使用shiro注解进行权限控制 //调用该方法,需要manager: delete权限 @RequiresPermissions("manager: delete") publicvoiddeleteIds()throwsException{ } 基于JSTL标签库的权限控制 在jsp页面中引入shiro的标签库 <%@taglibprefix="shiro"uri="http: //shiro.apache.org/tags"%> 使用shiro提供的标签进行权限控制 <%--拥有manager: view才会显示--%> hasPermissionname="manager: view"> hasPermission> 基于编程的权限控制 publicvoidedit()throwsException{ //编程实现权限控制 //调用Shiro框架提供的工具类,获取本地线程上的Subject对象 Subjectsubject=SecurityUtils.getSubject(); //检测权限,无则抛出异常 subject.checkPermission("manager: update"); } PS: 当尚未授予manager权限时,会抛出org.apache.shiro.authz.UnauthorizedException这个异常,所以注意捕获并处理这个异常。 如果使用Struts2框架,可以采取如下方式捕获并处理: --全局视图--> --全局异常捕获--> 使用ehcache缓存权限数据 引入ehcache的依赖 --引入ehcache的依赖--> 引入ehcache配置文件 xsi="http: //www.w3.org/2001/XMLSchema-instance" xsi: noNamespaceSchemaLocation="../config/ehcache.xsd"> maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" maxE
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Apache Shiro入门 Shiro 入门
![提示](https://static.bdocx.com/images/bang_tan.gif)