Apache Shiro 是一个强大且易用的 Java 安全框架,实行身份验证、授权、密码和会话管理。利用 Shiro 的易于理解的 API,您可以快速、轻松地得到任何运用程序,从最小的移动运用程序到最大的网络和企业运用程序。
二、Shiro 授权入门
大略先容完毕 shiro 的浸染后,接下来我们就直接进入 shiro 授权的入门,由于我们学习 shiro 重点是在利用,以是我们涉及到 shiro 源码的部分我们就不做过多的关注。
2.1:首先我们须要创建一个 maven 的 web 项目,导入 shiro 干系的依赖包和 tomcat 以及 jdk 的编译插件,本次我们利用 shiro 最新的依赖包。
大家也可以直接从 maven 的中心仓库找坐标
<groupId>cn.itcast</groupId><artifactId>shiro_quickStart</artifactId><version>1.0-SNAPSHOT</version><packaging>war</packaging><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency><dependency><groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId><version>1.4.1</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-web</artifactId><version>1.4.1</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.8</source><target>1.8</target></configuration></plugin><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.1</version><configuration><port>8989</port><path>/</path><uriEncoding>UTF-8</uriEncoding></configuration></plugin></plugins>
2.2 在项目的 WEB-INF 下去创建一个 shiro 的配置文件 shiro.ini,同时须要在 web.xml 中配置 shiro 核心的过滤器;
2.2.1 web.xml 中核心过滤器配置
<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>
2.2.2 shiro.ini 配置认证
大略阐明一下,users 是用来配置用户名和密码的,urls 是用来配置认证。/admin/=authc 表示访问项目 admin 下面的所有资源都须要登录认证,而/login /login.jsp 表示访问这 2 个资源不须要登录认证;
[main] [users] user=user admin=admin [urls] /admin/=authc /login=anon /login.jsp=anon
2.2.3 编写 LoginServlet 和 login.jsp
在 pom.xml 中引入 Servlet 和 Jsp 的依赖包
<dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.0.1</version><scope>provided</scope></dependency> <dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.1</version><scope>provided</scope></dependency>
创建 LoginServlet 和 login.jsp
启动测试:
当我们访问 //localhost:8989/admin/aa,由于须要登录认证,以是跳转到了登录页面;
三、Shiro 入门配置细节
上一讲当我们访问//localhost:8989/admin/aa,由于访问的资源须要登录认证跳转到了 login.jsp;为什么跳转到 login.jsp 页面了呢?
缘故原由是 shiro 利用了一些内置的过滤器;
我们可以通过查阅
源码,创造如果没有登录,自动跳转到 login.jsp
3.1 如何去配置登录页面;
3.2 如何让 shiro 完成登录认证(判断页面传入的用户名密码是精确的)
3.2.2 修正 login.jsp,加入表单,已经表单提交的地址
3.2.3 在 LoginServlet 完成登录认证
四、Shiro 授权入门
Shiro 除了可以完成认证外,也可以进行授权,即登任命户只有拥有指定的角色才能访问指定的资源;
4.1 修正 shiro.ini 文件,加入角色及授权。
4.2 [roles]中可以配置系统中的角色,此处我们定义了 2 个角色,一个角色为 ROLE_USER,一个为 ROLE_ADMIN
4.3[users]中除了可以配置登录的用户外,还可以给用户分配角色。此处我们定义 user 用户的角色为 ROLE_USER,admin 用户的角色为ROLE_ADMIN;
4. 4[urls]中除了可以配置资源访问是否须要登录认证,还可以配置登任命户访问资源须要哪些角色。此处我们定义访问/admin 下面的所有资源,除了须要登录,登任命户还须要有 ROLE_USER 角色;
4.5 测试我们创造如果利用 user/user 用户名和密码进行登录,登录成功后可以访问到/admin/add.jsp
而如果利用 admin/admin 用户名和密码进行登录登录成功后涌现 401 的缺点;
五、Shiro 认证流程和自定义 Realm
5.1 前 2 个章节我们已经讲解完毕,认证和授权的入门,接下来我们讲解认证流程;首先我们先来看一张图,授权流程图
流程:
1、当我们调用 Subject.login(token)进行登录,他会会自将 token 交由给 Security Manager,以是我们须要在调用 login 之前,在
SecurityUtils. setSecurityManager()设置 Security Manager;
2.SecurityManager 他会调用 Authenticator 进行用户名和密码的认证;
3、Authenticator 才是真正的身份验证者,Authenticator 会把相应的 token 传入 Realm,从 Realm 获取身份验证信息,如果没有返回/ 抛出非常表示认证失落败了。
对付开拓者来说;SecurityManager 和 Authenticator 都由 shiro 开拓好了,当然他也供应了自己供应的一些 Realm 来获取用户名和密码;
默认情形下 shiro 利用的是 initRealm(shiro.ini 配置文件中配置的用户名和密码)进行同户名和密码的获取,我们也可以自己定义 Realm 来获取
用户名和密码完成认证;
5.2:自定义 Realm
package cn.itcast.realm;import org.apache.shiro.authc.; import org.apache.shiro.realm.Realm;public class StaticRealm implements Realm {@Overridepublic String getName() {//指定Realm的名称return \"大众staticRealm\公众;}@Overridepublic boolean supports(AuthenticationToken token) {//该Realm支持的Token类型return token instanceof UsernamePasswordToken;}@Overridepublic AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throwsAuthenticationException {//获取token中的用户名和密码String username = String.valueOf(token.getPrincipal());String password = new String((char[]) token.getCredentials());//如果用户名密码不是gang/123抛出非常,认证失落败if(!username.equals(\"大众gang\公众) || !password.equals(\"大众123\公众)) { throw new AuthenticationException(\"大众用户名或者密码有误\"大众);}return new SimpleAuthenticationInfo(username,password,getName());}}
5.3 在 shiro.ini 中配置自定义的 Realm
5.4 测试自定义 Realm
经由测试我们创造原来的 iniRealm 就不中兴浸染,起浸染的便是我们自定义的 Realm。
5.5 我们在定义 Realm 的时候除了可以实现 Realm 接口也利用它已经实现的一些类;Realm 的体系构造如下;
个中 JdbcRealm 可以完成基于数据库的认证;
5.6、利用 JdbcRealm 来完成基于数据库的认证;
5.6.1 导入 MySQL 驱动及连接池的依赖包,我们本次利用 Druid 连接池
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.0.14</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.35</version></dependency>
5.6.2 在 mysql 中创建 2 张数据库表、
表构造必须和 JdbcRealm 中发送 SQL 语句的表构造同等;
表 1:用户表、用来存储用户名和密码
表 2:角色表、用来存储用户的角色信息
5.6.3 在 shiro.ini 中配置 JdbcRealm
5.6.4:测试
六、Shiro 授权流程
6.1 上一讲我们给大家讲解了 Shiro 认证的流程,紧张便是如何自定义 Realm,接下来我们要讲解的便是授权;首先我们看一张图授权流程图
流程如下:
1.首先当我们去调用 Subject.isPermitted/hasRole,他会调用 SecurityManager,而 SecurityManager 接着会调用 Authorizer 授权管理器;
2.Authorizer 是真正的授权者,如果我们调用如 isPermitted(“user:view”),其首先会通过 PermissionResolver 把字符串转换成相应的
Permission 实例;
3.在进行授权之前,其会调用相应的 Realm 获取 Subject 相应的角色/权限用于匹配传入的角色/权限;
4.Authorizer 会判断 Realm 的角色/权限是否和传入的匹配,如果有多个 Realm,会调用 ModularRealmAuthorizer 进行循环判断,如果匹配如 isPermitted/hasRole会返回 true,否 则返回 false 表示授权失落败。
6.2 接下来我们通过一个入门案例,进行一个直不雅观的感想熏染;
6.2.2 首先我们先切换到 initRealm,注释掉 jdbcRealm。给 user/user 指定 ROLE_USER 角色、给 admin/admin 指定 ROLE_ADMIN 的角色
6.2.3 在用户登录成功后判断其是否有对应的角色
6.2.4 通过测试我们创造如果利用 admin/admin 登录,打印的是 true。
如果利用 user/user 登录,打印的是 false。
6.2.5 除了可以配置角色外,我们还可以配置权限;接下来我们来配置权限
ROLE_USER=user: 、
表示 ROLE_USER 角色拥有 user:的权限,表示任意
ROLE_ADMIN=admin:,user:
表示 ROLE_AMIN 角色拥有 admin:和 user:的权限,表示任意
/res/update.jsp=perms[user:add]
表示访问/admin/update.jsp 须要登录,并且须要 user:add 权限;
通过测试我们创造
user/user 和 user/admin 登录后都可以访问/res/update.jsp 资源但是 admin/admin 不能访问/admin/下面的资源
6.2.6自定义Realm完成认证和授权。要想利用自定义Relam 完成认证和授权,建议继续AuthorizingRealm
public class MyAuthorizingRealm extends AuthorizingRealm {/ 该方法是进行授权的 @param principals @return/ @Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();//给上岸用户指定角色USER_ROLEinfo.addRole(\"大众ROLE_ADMIN\"大众);//给登任命户指定权限info.addStringPermission(\"大众user:add\公众);return info;}/ 该方法是用来进行认证的/ @Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {String username = (String) token.getPrincipal();String password = new String((char[]) token.getCredentials());//如果用户名密码是gang/123if(username.equals(\公众gang\公众) && password.equals(\"大众123\"大众)) { return new SimpleAuthenticationInfo(username, password, getName());}else { throw new AuthenticationException(\"大众用户名或者密码缺点\"大众);}}
6.2.6 配置自定义 Realm
6.2.6 测试;利用 gang/li 登录后拥有角色 ROLE_ADMIN 和权限 user:add.不能访问/admin/add.jsp 但是可以访问/res/update.jsp
七、Spring 整合 shiro
在实际开拓中我们常日都不会单独利用 shiro,都是和 spring 进行整合,接下来我们要完成 spring 和 shiro 整合;
7.1:
导入 spring 和 shiro 整合干系依赖包
<dependency><groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId><version>1.4.1</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>5.0.5.RELEASE</version></dependency> <dependency><groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId><version>1.4.1</version></dependency>
7.2:编写 spring 的配置文件 applicationContext.xml
<?xml version=\"大众1.0\"大众 encoding=\"大众UTF-8\"大众?><beans xmlns=\"大众http://www.springframework.org/schema/beans\"大众xmlns:xsi=\"大众http://www.w3.org/2001/XMLSchema-instance\公众 xsi:schemaLocation=\"大众http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\公众><!--配置自定义Releam--><bean id=\公众myAuthorizingRealm\"大众 class=\公众cn.itcast.realm.MyAuthorizingRealm\公众></bean><!--配置认证管理器--><bean id=\"大众securityManager\"大众 class=\"大众org.apache.shiro.web.mgt.DefaultWebSecurityManager\"大众><property name=\"大众realm\"大众 ref=\"大众myAuthorizingRealm\"大众></property></bean><!--配置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=\"大众/admin/add.jsp\"大众/><!--未授权的页面--><property name=\"大众unauthorizedUrl\"大众 value=\"大众/401.jsp\"大众/> <property name=\"大众filterChainDefinitions\"大众> <value>/admin/=authc,roles[ROLE_USER]/login=anon/res/update.jsp=perms[user:add]/logout=logout</value></property></bean></beans>
7.2 在 web.xml 中利用 ContextLoaderListener 加载 spring 的配置文件.
<!--加载spring的配置文件--><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext.xml</param-value></context-param><!--配置shiro的代理过滤器--><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><filter-mapping><filter-name>shiroFilter</filter-name><url-pattern>/</url-pattern></filter-mapping>
学习资料:
权限管理实战:SpringBoot与Shiro整合