Shiro入门学习二
来源:互联网 发布:51单片机有趣的小制作 编辑:程序博客网 时间:2024/05/19 14:02
Shiro入门学习二
Apache Shiro是Java的一个安全(权限)框架
Shiro相比于Spring security更加便捷,不仅使用Java Se环境,也可以用在Java EE环境
Shiro的作用:
- 认证 - 例如登录
- 授权 - 权限管理
- 加密 - 例如密码可以用Shiro进行加密
- 会话管理 -
- web继承
- 缓存
Shiro功能简介
- Authentication:身份认证/登录,验证用户是不是拥有相应的身份;
- Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;
- Session Manager:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境的,也可以是如Web环境的;
- Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;
- Web Support:Web支持,可以非常容易的集成到Web环境;
- Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率;
- Concurrency:shiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;
- Testing:提供测试支持;
- Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;
- Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。
记住一点,Shiro不会去维护用户、维护权限;这些需要我们自己去设计/提供;然后通过相应的接口注入给Shiro即可。
Shiro的架构(对使用者)
- Subject - 代表当前的用户
- Shiro SecurityManager - 安全管理器
- Realm - Shiro从Realm获取安全数据(如用户、角色、权限)
Shiro环境的搭建
JavaSE环境搭建Shiro框架
1.所需要的jar包
- apache-log4j-1.2.15.jar
- shiro-all-1.3.2.jar
- slf4j-log4j12-1.6.1.jar
- slf4j.api-1.6.1.jar
2.配置文件
可以从Shiro源码文件中的sample中拷贝过来
shiro.ini
文件:存储数据,如用户名、密码、角色、权限log4j.properties
shiro.ini
文件内容及说明:
1.shiro中user存储数据格式
用户名=密码, 角色1, 角色2......
一个用户名可以有多个角色,如:
[users]# user 'root' with password 'secret' and the 'admin' role# 用户 root 密码 secret 角色 adminroot = secret, admin# user 'guest' with the password 'guest' and the 'guest' role# 用户 guest 密码 guest 角色 guestguest = guest, guest# user 'presidentskroob' with password '12345' ("That's the same combination on# my luggage!!!" ;)), and role 'president'# 用户 presidentskroob 密码 12345 角色 presidentpresidentskroob = 12345, president# user 'darkhelmet' with password 'ludicrousspeed' and roles 'darklord' and 'schwartz'# 用户 darkhelmet 密码 ludicrousspeed 角色 darklord schwartzdarkhelmet = ludicrousspeed, darklord, schwartz# user 'lonestarr' with password 'vespa' and roles 'goodguy' and 'schwartz'# 用户 lonestarr 密码 vespa 角色 goodguy schwartzlonestarr = vespa, goodguy, schwartz
2.一个角色可能会对个多个权限
[roles]# 'admin' role has all permissions, indicated by the wildcard '*'# admin 具有所有权限admin = *# The 'schwartz' role can do anything (*) with any lightsaber:schwartz = lightsaber:*# The 'goodguy' role is allowed to 'drive' (action) the winnebago (type) with# license plate 'eagle5' (instance specific id)goodguy = winnebago:drive:eagle5
3.测试获取session对象
如下的HelloWorld
类:
package com.shiro.bean;import org.apache.shiro.SecurityUtils;import org.apache.shiro.config.IniSecurityManagerFactory;import org.apache.shiro.mgt.SecurityManager;import org.apache.shiro.session.Session;import org.apache.shiro.subject.Subject;import org.apache.shiro.util.Factory;import org.slf4j.Logger;import org.slf4j.LoggerFactory;public class HelloWorld { private static final Logger log = LoggerFactory.getLogger(HelloWorld.class); public static void main(String[] args) { log.info("正在测试log4j......"); //1.获取安全管理器 Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini"); SecurityManager securityManager = factory.getInstance(); //2.设置安全管理器 SecurityUtils.setSecurityManager(securityManager); //3.获取Subject对象,为即将登录的用户 Subject currentUser = SecurityUtils.getSubject(); //4.获取session Session session = currentUser.getSession(); session.setAttribute("name", "wz"); String value = (String) session.getAttribute("name"); if (value != null ) { log.info("Shiro获取session会话对象当中指定的值:" + value); } }}
运行后,在控制台正确的输出了结果
Shiro认证过程
Shiro认证过程可参阅官网Authentication Sequence,如下图所示:
1.判断currentUser
是否登录过,currentUser.isAuthenticated() == false
表示没有登录过
2.如果没有登录过,需要给当前的subject设置用户名和密码,使用UsernamePasswordToken
3.登录,可能会抛出如下的异常
UnknownAccountException
- 错误的帐号IncorrectCredentialsException
- 错误的凭证LockedAccountException
- 锁定的帐号DisabledAccountException
- 禁用的帐号ExcessiveAttemptsException
- 登录失败次数过多ExpiredCredentialsException
- 过期的凭证
代码如下:
if (currentUser.isAuthenticated() == false) { UsernamePasswordToken token = new UsernamePasswordToken("root", "secret"); token.setRememberMe(true);//记住我 try { currentUser.login(token); log.info("用户名和密码正确"); } catch (UnknownAccountException e) { log.info("账户不存在"); }catch (IncorrectCredentialsException e) { log.info("密码错误"); }catch (LockedAccountException e) { log.info("用户已经锁死"); }catch (AuthenticationException e) { log.info("认证异常"); } }
Shiro角色、权限认证过程
1.判断某个用户拥有指定的角色
if (currentUser.hasRole("admin")) { log.info("拥有指定的角色"); }else{ log.info("不拥有指定的角色"); }
2.判断某个用户拥有指定的权限
if (currentUser.isPermitted("winnebago:drive:eagle5")) { log.info("拥有指定的权限"); }else{ log.info("不拥有指定的权限"); }
Shiro Web-App 搭建
参考官网Securing Web Applications with Apache Shiro,使用maven来搭建一个Web-App的shiro项目,可以在Github上fork一个tutorial project,看参考pom.xml
中内容
主要步骤是:
1.在src/main/webapp/WEB-INF/shiro.ini
目录下创建shiro.ini
文件
2.在web.xml
中启用shiro
<listener> <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class></listener><filter> <filter-name>ShiroFilter</filter-name> <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class></filter><filter-mapping> <filter-name>ShiroFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> <dispatcher>ERROR</dispatcher></filter-mapping>
默认过滤器
默认过滤器的介绍参考Default Filters
Shiro Spring、SpringMVC框架搭建
1.在web.xml
中配置shiroFilter
<!-- Shiro Filter is defined in the spring application context: --> <!-- Filter的代理类 --> <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>
Shiro提供了与Web集成的支持,其通过一个ShiroFilter
入口来拦截需要安全控制的URL,然后进行相应的控制
ShiroFilter
类似于Strut2
/SpringMVC
这种web框架的前端控制器,是安全控制的入口点,其负责读取配置(如ini配置文件),然后判断URL是否需要登录/权限等工作
ShiroFilter
如何控制哪些web资源是需要登录才能访问,哪些不需要?
ShiroFilter
提供了2中方式:
filterChainDefinitions
过滤链的定义- 如果是没有经过认证,则会自动走到
loginUrl
DelegatingFilterProxy
的作用是自动到Spring容器查找名为shiroFilter
(filter-name)的bean,并把Filter的操作委托给它。
DelegatingFilterProxy
其源码定义如下:
public class DelegatingFilterProxy extends GenericFilterBean { private String contextAttribute; private WebApplicationContext webApplicationContext; private String targetBeanName; private boolean targetFilterLifecycle = false; private volatile Filter delegate; ......
其中:
targetBeanName
- 存储即将获取的shiro核心过滤器的id值,如果没有指定这个targetBeanName,则自动获取filter的名字delegate
- 代表获取Spring的shiro的核心过滤器
2.Spring配置文件中shiro的配置
Spring配置文件applicationContext.xml
中shiro的配置,可在shiro的源码文件中的sample例子找到,如下:
这里推荐大家参考在 Web 项目中应用 Apache Shiro
applicationContext.xml
中shiro的配置内容如下:
<!-- 安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <!-- 缓存管理器 --> <property name="cacheManager" ref="cacheManager" /> <!-- 处理数据 --> <property name="realm" ref="jdbcRealm" /> </bean> <!-- 可以使用的缓存技术,这里默认使用EHCACH --> <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"> <!-- 缓存的位置 --> <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"/> </bean> <!-- Realm --> <bean id="jdbcRealm" class="com.shiro.bean.ShiroRealm"> </bean> <!-- 必须要有这样的实例,用来管理spring容器当中的shiro常见的对象 --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" /> <!-- 启用shiro注解 --> <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> <!-- 网络方面 --> <bean id="secureRemoteInvocationExecutor" class="org.apache.shiro.spring.remoting.SecureRemoteInvocationExecutor"> <property name="securityManager" ref="securityManager" /> </bean> <!-- 配置过滤器 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager" /> <!-- 登录页面 --> <property name="loginUrl" value="/logon.jsp" /> <!-- 认证登录成功后跳转的页面 --> <property name="successUrl" value="/s/index" /> <!-- 未授权的页面 --> <property name="unauthorizedUrl" value="/abc.jsp" /> <!-- 过滤链的定义 --> <property name="filterChainDefinitions"> <value> /logon.jsp = anon /** = authc </value> </property> </bean>
一些说明:
1.securityManager
中 realm
属性,配置为我们自己实现的 Realm
2.shiroFilter
这个bean
的id
必须要与web.xml
文件中的filter-name
一致
loginUrl
- 登录页面地址successUrl
- 为登录成功页面地址(如果首先访问受保护 URL 登录成功,则跳转到实际访问页面)unauthorizedUrl
- 认证未通过访问的页面
3.shiroFilter
中 filterChainDefinitions
属性
anon
- 表示匿名访问(不需要认证与授权)authc
- 表示需要认证
这样配置后,假设我现在访问http://localhost:8080/ShiroDemo02/success.jsp
页面,则会自动跳转到http://localhost:8080/ShiroDemo02/logon.jsp
,其响应头为:
其中302
表示重定向
认证资源格式及URL匹配模型
[urls]
部分的配置,其格式是 url=拦截器[参数],拦截器[参数]
如果当前请求的url匹配[urls]
部分的某个url模式,将会执行其配置的拦截器
URL匹配模式
url模式使用Ant风格模式
Ant路劲通配符支持?
、*
、**
,注意通配符匹配不包括目录分隔符”/”
?
- 匹配一个字符,如/admin?
将匹配/admin1
,但不匹配/admin
或/admin/
*
- 匹配零个或多个字符串,如/admin
将匹配/admin
、/admin123
,但不匹配/admin/1
**
- 匹配路劲中的零个或多个路径,如/admin/**
将匹配/admin/a
或/admin/a/b
URL匹配顺序
URL
权限采取第一次匹配优先的方式,即从头开始使用第一个匹配的url模式对应的拦截器链
如:
- /bb/**= filter1
- /bb/aa = filter2
- /** = filter3
如果请求的url是"/bb/aa"
,因为按照声明顺序进行匹配,那么将使用filter1进行拦截
JSP标签
JSP标签参考JSP / GSP Tag Library,也可参阅第九章 JSP标签——《跟我学Shiro》
导入标签库
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
1.principal标签
<shiro: principal/>
显示用户身份信息,默认调用Subject.getPrincipal()
获取,即Primary Principal。
2.guest标签
用户没有身份验证时显示相应信息,即游客访问信息。
3.user标签
用户已经身份验证/记住我登录后显示相应的信息。
4.hasPermission标签
如果当前Subject有权限将显示body体内容。
<shiro:hasPermission name="user:add"><a href="<%=path %>/user/add.jsp">用户添加</a><br/></shiro:hasPermission>
5.hasRole标签
如果当前Subject有角色将显示body体内容。
<shiro:hasRole name="admin"><a href="<%=path %>/admin/">管理员页面</a><br/></shiro:hasRole>
教程
- 在 Web 项目中应用 Apache Shiro
- Shiro入门学习二
- Shiro入门学习二
- Shiro学习总结(二)--Shiro的入门小例子
- shiro学习(二)---授权入门程序
- Shiro入门学习一
- Shiro入门学习三
- Shiro入门学习四
- Shiro入门学习一
- Shiro入门学习五
- Shiro入门学习三
- shiro入门学习四
- Shiro入门学习六
- shiro学习(二) Realm
- Shiro 学习记录 Shiro 入门程序
- Shiro学习笔记<1>入门--Hello Shiro
- 权限学习--Shiro入门学习
- shiro基础学习(二) shiro认证
- shiro基础学习(二)—shiro认证
- [NOIP模拟][贪心]打牌
- Dapper
- noteBook2.9-C#基础第九天字符串
- cf,A. Mashmokh and Lights
- 函数
- Shiro入门学习二
- 大数据-时下已经大火的技术
- [NOIP模拟][规律探究]弹球
- 判断字符串是否是回文
- 透视变换实现代码(全)
- linux每天一命令: chmod 修改档案权限
- 数据结构 折半查找法(算法思想和源代码)
- [NOIP模拟][匈牙利算法][费用流]放盒子
- CentOS7 yum源 快速转 阿里云