目录
3.1.2 通过web.xml将shiro与web容器进行集成
shiro是apache的一个开源框架,是一个权限管理的框架,可以实现 用户认证、用户授权。
shiro不依赖于spring,不仅可以实现 web应用的权限管理,还可以实现c/s系统、分布式系统权限管理,shiro属于轻量框架,越来越多企业项目开始使用shiro。
Subject:主体,代表了当前“用户”,它只是一个抽象概念;
与Subject的所有交互都会委托给SecurityManager;
可以把Subject认为是一个门面;SecurityManager才是实际的执行者;
SecurityManager:安全管理器;它管理着所有Subject;可以看出它是Shiro 的核心,它负责与后边介绍的其他组件进行交互,如果学习过SpringMVC,你可以把它看成DispatcherServlet前端控制器;
Realm:域,Shiro从从Realm获取安全数据(如用户、角色、权限),就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm看成DataSource,即安全数据源。
1、subject:主体,可以是用户也可以是程序,主体要访问系统,系统需要对主体进行认证、授权。
2、securityManager:安全管理器,主体进行认证和授权都是通过securityManager进行。securityManager是一个集合,真正做事的不是securityManager而是它里面的东西。
3、authenticator:认证器,主体进行认证最终通过authenticator进行的。
4、authorizer:授权器,主体进行授权最终通过authorizer进行的。
5、sessionManager:web应用中一般是用web容器(中间件tomcat)对session进行管理,shiro也提供一套session管理的方式。
shiro不仅仅可以用于web管理也可以用于cs管理,所以他不用web容器的session管理。
6、SessionDao: 通过SessionDao管理session数据,针对个性化的session数据存储需要使用sessionDao(如果用tomcat管理session就不用SessionDao,如果要分布式的统一管理session就要用到SessionDao)。
7、cache Manager:缓存管理器,主要对session和授权数据进行缓存(权限管理框架主要就是对认证和授权进行管理,session是在服务器缓存中的),比如将授权数据通过cacheManager进行缓存管理和ehcache整合对缓存数据进行管理(redis是缓存框架)。
8、realm:域,领域,相当于数据源,通过realm存取认证、授权相关数据(原来是通过数据库取的)。
注意:authenticator认证器和authorizer授权器调用realm中存储授权和认证的数据和逻辑。
9、cryptography:密码管理,比如md5加密,提供了一套加密/解密的组件,方便开发。比如提供常用的散列、加/解密等功能。比如 md5散列算法(md5只有加密没有解密)。

对Shiro框架的简介做个总结,它的主要作用:
① 认证 ---> 接管了用户登录操作;
② 授权 ---> 接管了系统资源的分配;
③ 会话管理 ---> 接管了tomcat中的session;
④ 缓存管理 ---> 主要提升了权限管理的执行效率;
⑤ 密码管理 ---> 对密码进行加密;
由于shiro与日志有所关系,所以我们还是先导入日志配置文件;
log4j2.xml
- "1.0" encoding="UTF-8"?>
-
- <Configuration status="WARN" monitorInterval="30">
- <Properties>
-
- <Property name="LOG_HOME">/root/workspace/lucenedemo/logsProperty>
- <property name="ERROR_LOG_FILE_NAME">/root/workspace/lucenedemo/logs/errorproperty>
- <property name="WARN_LOG_FILE_NAME">/root/workspace/lucenedemo/logs/warnproperty>
- <property name="PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} [%t-%L] %-5level %logger{36} - %msg%nproperty>
- Properties>
-
- <Appenders>
-
- <Console name="Console" target="SYSTEM_OUT">
-
- <ThresholdFilter level="trace" onMatch="ACCEPT"
- onMismatch="DENY" />
-
-
- <PatternLayout pattern="${PATTERN}" />
- Console>
-
-
-
- <File name="log" fileName="logs/test.log" append="false">
- <PatternLayout
- pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
- File>
-
- <RollingFile name="RollingFileInfo" fileName="${LOG_HOME}/info.log"
- filePattern="${LOG_HOME}/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log">
-
- <ThresholdFilter level="info" onMatch="ACCEPT"
- onMismatch="DENY" />
- <PatternLayout
- pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
- <Policies>
-
-
-
- <TimeBasedTriggeringPolicy interval="1"
- modulate="true" />
-
-
- Policies>
- RollingFile>
-
- <RollingFile name="RollingFileWarn" fileName="${WARN_LOG_FILE_NAME}/warn.log"
- filePattern="${WARN_LOG_FILE_NAME}/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log">
- <ThresholdFilter level="warn" onMatch="ACCEPT"
- onMismatch="DENY" />
- <PatternLayout
- pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
- <Policies>
- <TimeBasedTriggeringPolicy />
- <SizeBasedTriggeringPolicy size="2 kB" />
- Policies>
-
- <DefaultRolloverStrategy max="20" />
- RollingFile>
-
- <RollingFile name="RollingFileError" fileName="${ERROR_LOG_FILE_NAME}/error.log"
- filePattern="${ERROR_LOG_FILE_NAME}/$${date:yyyy-MM}/error-%d{yyyy-MM-dd-HH-mm}-%i.log">
- <ThresholdFilter level="error" onMatch="ACCEPT"
- onMismatch="DENY" />
- <PatternLayout
- pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
- <Policies>
-
- <TimeBasedTriggeringPolicy interval="1"
- modulate="true" />
-
- Policies>
- RollingFile>
-
- Appenders>
-
-
- <Loggers>
-
- <logger name="org.springframework" level="INFO">logger>
- <logger name="org.mybatis" level="INFO">logger>
-
-
- <logger name="org.springframework" level="ERROR" />
- <logger name="org.hibernate" level="ERROR" />
- <logger name="org.apache.struts2" level="ERROR" />
- <logger name="com.opensymphony.xwork2" level="ERROR" />
- <logger name="org.jboss" level="ERROR" />
-
-
- <root level="all">
- <appender-ref ref="Console" />
- <appender-ref ref="RollingFileInfo" />
- <appender-ref ref="RollingFileWarn" />
- <appender-ref ref="RollingFileError" />
- root>
-
- Loggers>
-
- Configuration>
- "1.0" encoding="UTF-8"?>
-
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0modelVersion>
-
- <groupId>org.examplegroupId>
- <artifactId>shiroartifactId>
- <version>1.0-SNAPSHOTversion>
- <packaging>warpackaging>
-
- <name>shiro Maven Webappname>
-
- <url>http://www.example.comurl>
-
- <properties>
- <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
- <maven.compiler.source>1.7maven.compiler.source>
- <maven.compiler.target>1.7maven.compiler.target>
- <maven.compiler.plugin.version>3.7.0maven.compiler.plugin.version>
-
-
- <junit.version>4.12junit.version>
- <servlet.version>4.0.0servlet.version>
- <log4j2.version>2.9.1log4j2.version>
- <slf4j.version>1.7.7slf4j.version>
- <log4j2.disruptor.version>3.2.0log4j2.disruptor.version>
-
- <shiro.version>1.2.5shiro.version>
- properties>
-
- <dependencies>
-
- <dependency>
- <groupId>org.apache.shirogroupId>
- <artifactId>shiro-coreartifactId>
- <version>${shiro.version}version>
- dependency>
-
- <dependency>
- <groupId>org.apache.shirogroupId>
- <artifactId>shiro-webartifactId>
- <version>${shiro.version}version>
- dependency>
-
- <dependency>
- <groupId>junitgroupId>
- <artifactId>junitartifactId>
- <version>${junit.version}version>
- <scope>testscope>
- dependency>
-
- <dependency>
- <groupId>javax.servletgroupId>
- <artifactId>javax.servlet-apiartifactId>
- <version>${servlet.version}version>
- <scope>providedscope>
- dependency>
-
- <dependency>
- <groupId>org.slf4jgroupId>
- <artifactId>slf4j-apiartifactId>
- <version>${slf4j.version}version>
- dependency>
- <dependency>
- <groupId>org.slf4jgroupId>
- <artifactId>jcl-over-slf4jartifactId>
- <version>${slf4j.version}version>
- <scope>runtimescope>
- <exclusions>
- <exclusion>
- <artifactId>slf4j-apiartifactId>
- <groupId>org.slf4jgroupId>
- exclusion>
- exclusions>
- dependency>
-
- <dependency>
- <groupId>org.apache.logging.log4jgroupId>
- <artifactId>log4j-slf4j-implartifactId>
- <version>${log4j2.version}version>
- <exclusions>
- <exclusion>
- <artifactId>slf4j-apiartifactId>
- <groupId>org.slf4jgroupId>
- exclusion>
- exclusions>
- dependency>
-
- <dependency>
- <groupId>org.apache.logging.log4jgroupId>
- <artifactId>log4j-apiartifactId>
- <version>${log4j2.version}version>
- dependency>
- <dependency>
- <groupId>org.apache.logging.log4jgroupId>
- <artifactId>log4j-coreartifactId>
- <version>${log4j2.version}version>
- dependency>
-
- <dependency>
- <groupId>org.apache.logging.log4jgroupId>
- <artifactId>log4j-webartifactId>
- <version>${log4j2.version}version>
- <scope>runtimescope>
- dependency>
-
- <dependency>
- <groupId>com.lmaxgroupId>
- <artifactId>disruptorartifactId>
- <version>${log4j2.disruptor.version}version>
- dependency>
-
- dependencies>
-
- <build>
- <finalName>shirofinalName>
- <resources>
-
- <resource>
- <directory>src/main/javadirectory>
- <includes>
- <include>**/*.xmlinclude>
- includes>
- resource>
-
- <resource>
- <directory>src/main/resourcesdirectory>
- <includes>
- <include>*.propertiesinclude>
- <include>*.xmlinclude>
- <include>*.iniinclude>
- includes>
- resource>
- resources>
- <pluginManagement>
- <plugins>
-
- <plugin>
- <groupId>org.apache.maven.pluginsgroupId>
- <artifactId>maven-compiler-pluginartifactId>
- <version>${maven.compiler.plugin.version}version>
- <configuration>
- <source>${maven.compiler.source}source>
- <target>${maven.compiler.target}target>
- <encoding>${project.build.sourceEncoding}encoding>
- configuration>
- plugin>
- <plugin>
- <artifactId>maven-clean-pluginartifactId>
- <version>3.1.0version>
- plugin>
-
- <plugin>
- <artifactId>maven-resources-pluginartifactId>
- <version>3.0.2version>
- plugin>
- <plugin>
- <artifactId>maven-compiler-pluginartifactId>
- <version>3.8.0version>
- plugin>
- <plugin>
- <artifactId>maven-surefire-pluginartifactId>
- <version>2.22.1version>
- plugin>
- <plugin>
- <artifactId>maven-war-pluginartifactId>
- <version>3.2.2version>
- plugin>
- <plugin>
- <artifactId>maven-install-pluginartifactId>
- <version>2.5.2version>
- plugin>
- <plugin>
- <artifactId>maven-deploy-pluginartifactId>
- <version>2.8.2version>
- plugin>
- plugins>
- pluginManagement>
- build>
- project>
shiro.ini(就是放的用户信息)
- [users]
- zs=123
- ls=456
- ww=789
使用步骤:① 获取工厂对象;
② 获取实例;
③ 将实例交给SecurityUtils;
④ 获取登录主体;
⑤ 生成token令牌;(用户名密码)
⑥ 主体携带令牌进行登录;
我们建立一个测试类来依次实现:
Demo1
- package com.leaf.demo;
-
- import org.apache.shiro.SecurityUtils;
- import org.apache.shiro.authc.UsernamePasswordToken;
- import org.apache.shiro.config.IniSecurityManagerFactory;
- import org.apache.shiro.mgt.SecurityManager;
- import org.apache.shiro.subject.Subject;
-
- /**
- * @author Leaf
- * @site 2977819715
- * @company 玉渊工作室
- * @create 2022-08-25 0:32
- */
- public class Demo1 {
-
- public static void main(String[] args) {
- /*获取工厂对象;
- 获取实例;
- 将实例交给SecurityUtils;
- 获取登录主体;
- 生成令牌;
- 主体携带令牌进行登录;*/
- //工厂
- IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro.ini");
- //获取安全管理器的实例
- SecurityManager instance = factory.getInstance();
- SecurityUtils.setSecurityManager(instance);
- //获取登录主体
- Subject subject = SecurityUtils.getSubject();
- //令牌
- UsernamePasswordToken token = new UsernamePasswordToken("zs", "999");
- //主体登录
- subject.login(token);
- System.out.println("登录成功");
- subject.logout();
- System.out.println("登出成功");
-
- }
-
- }
我们故意放入错误的用户信息,然后运行测试一下: 
然后我们再把用户信息改正确,再次测试:
- //令牌
- UsernamePasswordToken token = new UsernamePasswordToken("zs", "123");
登录成功:
实现步骤:1)web.xml文件中进行shiro过滤器配置
2)添加配置文件 shiro-web.ini
shiro-web.ini
- [main]
- #定义身份认证失败后的请求url映射,loginUrl是身份认证过滤器中的一个属性
- authc.loginUrl=/login
- #定义角色认证失败后的请求url映射,unauthorizedUrl是角色认证过滤器中的一个属性
- roles.unauthorizedUrl=/unauthorized.jsp
- #定义权限认证失败后请求url映射,unauthorizedUrl是角色认证过滤器中的一个属性
- perms.unauthorizedUrl=/unauthorized.jsp
-
- [users]
- zs=123,role1
- ls=123,role2
- ww=123,role3
- zdm=123,admin
-
-
- [roles]
- role1=user:create
- role2=user:create,user:update
- role3=user:create,user:update,user:delete,user:view,user:load
- admin=user:*
-
-
-
- #定义请求的地址需要做什么验证
- [urls]
- #请求login的时候不需要权限,游客身份即可(anon)
- /login.do=anon
-
- #请求/user/updatePwd.jsp的时候,需要身份认证(authc)
- /user/updatePwd.jsp=authc
-
- #请求/admin的时候,需要角色认证,必须是拥有admin角色的用户才行
- /admin/*.jsp=roles[admin]
- #请求/teacher的时候,需要权限认证,必须是拥有user:create权限的角色的用户才行
- /user/teacher.jsp=perms["user:update"]
web.xml
- "1.0" encoding="UTF-8"?>
- <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
- version="3.1">
- <display-name>Archetype Created Web Applicationdisplay-name>
- <context-param>
- <param-name>shiroConfigLocationsparam-name>
- <param-value>classpath:shiro-web.iniparam-value>
- context-param>
- <listener>
- <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListenerlistener-class>
- listener>
-
- <filter>
- <filter-name>ShiroFilterfilter-name>
- <filter-class>org.apache.shiro.web.servlet.ShiroFilterfilter-class>
- filter>
- <filter-mapping>
- <filter-name>ShiroFilterfilter-name>
- <url-pattern>/*url-pattern>
- filter-mapping>
-
- web-app>
LoginServlet
- package com.leaf.demo;
-
- import org.apache.shiro.SecurityUtils;
- import org.apache.shiro.authc.UsernamePasswordToken;
- import org.apache.shiro.subject.Subject;
-
- import javax.servlet.ServletException;
- import javax.servlet.annotation.WebServlet;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
-
- /**
- * @author Leaf
- * @site 2977819715
- * @company 玉渊工作室
- * @create 2022-08-25 1:59
- */
- @WebServlet("/login")
- public class LoginServlet extends HttpServlet {
-
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- doPost(req,resp);
- }
-
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- String username = req.getParameter("username");
- String password = req.getParameter("password");
- UsernamePasswordToken token = new UsernamePasswordToken(username, password);
- Subject subject = SecurityUtils.getSubject();
- try {
- subject.login(token);
- req.getRequestDispatcher("/main.jsp").forward(req,resp);
- }catch (Exception e){
- req.setAttribute("message","用户名密码输入有误!!!");
- req.getRequestDispatcher("/login.jsp").forward(req,resp);
- }
-
- }
- }
LogoutServlet
- package com.leaf.demo;
-
- import org.apache.shiro.SecurityUtils;
- import org.apache.shiro.authc.UsernamePasswordToken;
- import org.apache.shiro.subject.Subject;
-
- import javax.servlet.ServletException;
- import javax.servlet.annotation.WebServlet;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
-
- /**
- * @author Leaf
- * @site 2977819715
- * @company 玉渊工作室
- * @create 2022-08-25 2:08
- */
- @WebServlet("/logout")
- public class LogoutServlet extends HttpServlet {
-
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- doPost(req,resp);
- }
-
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- Subject subject = SecurityUtils.getSubject();
- try {
- subject.logout();
- req.getRequestDispatcher("/login.jsp").forward(req,resp);
- }catch (Exception e){
- req.getRequestDispatcher("/login.jsp").forward(req,resp);
- }
-
- }
-
- }



由于这个前端页面太多,不好粘在这里,就直接放在百度网盘上,需要的自行领取;
链接:https://pan.baidu.com/s/1QGmS3QzEZmnjjvWb9jSagQ
提取码:Leaf
注:把jsp解压后,把jsp下级目录的所有文件直接粘贴到idea的webapp中,不要复制错目录结构!
接着我们就可以来开始测试:
