第八节 与WEB集成实例分析
前言
与WEB集成想了一下,还是要弄一个例子。至少应该展示一下拦截器的基本用法。如果你有幸看到这里,希望你能继续跟着大宇的思路走下去。我将想你展示我编写代码的流程。与Spring集成先不要着急,我会在后面的小节详细向你讲述。现在,让我们先来搞定一个简单的Shiro与WEB集成的例子。本小节的流程是:导入依赖、设置web.xml、编写java、配置shiro.ini、最后编写JSP。下一小节分析Shiro标签将以本小节作为WEB环境。
本章节项目源码:点击我下载源码
一、导入依赖
首先创建本章节需要的依赖包。仔细查看,除了Shiro的3个依赖包以外,还多出了一个Servlet依赖包。最下面导入JSTL标签库。
<dependencies>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies>
二、设置web.xml
在第六节中已经分析过了与WEB集成的原理:第六节 与WEB集成原理分析。首先要指定两个全局变量的值,再配置一个监听器,让其在服务器启动的时候加载Shiro环境。所以,让我们直接编写我们的web.xml吧。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name>Archetype Created Web Application</display-name>
<!-- 初始化SecurityManager对象所需要的环境-->
<context-param>
<param-name>shiroEnvironmentClass</param-name>
<param-value>org.apache.shiro.web.env.IniWebEnvironment</param-value>
</context-param>
<!-- 指定Shiro的配置文件的位置 -->
<context-param>
<param-name>shiroConfigLocations</param-name>
<param-value>classpath:shiro.ini</param-value>
</context-param>
<!-- 监听服务器启动时,创建shiro的web环境。
即加载shiroEnvironmentClass变量指定的IniWebEnvironment类-->
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>
<!-- shiro的l拦截入口,拦截一切请求 -->
<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>
</filter-mapping>
</web-app>
三、编写Java
现在先不依赖任何的框架,先编写一套基本的Servlet。
下面的Java文件算是非常简单了。也就是从GET请求路径中获取用户的帐号密码,将其交付给Shiro环境进行认证。如果认证成功,跳转loginSuccess.jsp。如果认证失败,跳转loginFailure.jsp。
package action;
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 jay.zhou
* @date 2018/12/26
* @time 7:41
*/
@WebServlet(name = "LoginServlet", urlPatterns = "/authen")
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");
//封装用户数据,成为Shiro能认识的token标识
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
//将封装用户信息的token进行验证
boolean isLoginSuccess = login(token);
if (!isLoginSuccess) {
//重定向到未登录成功页面
resp.sendRedirect("loginFailure.jsp");
return;
}
req.getRequestDispatcher("loginSuccess.jsp").forward(req, resp);
}
/**
* 用于验证用户的帐号密码信息是否合法
*
* @param token 封装着用户的帐号密码的UsernamePasswordToken
* @return 用户输入的信息是否合法
*/
private boolean login(UsernamePasswordToken token) {
//从shiro环境中获取门面Subject
Subject subject = SecurityUtils.getSubject();
try {
//认证,内部读取shiro.ini文件进行帐号匹配
subject.login(token);
} catch (Exception e) {
return false;
}
return subject.isAuthenticated();
}
}
四、配置shiro.ini
shiro.ini我尽量编写的简单一点。这里就不自定义Realm作为认证的数据源了。为了简单起见,直接在shiro.ini配置文件中配置了用户的帐号密码,以及其权限信息。jay / 123456 是本项目的唯一合法用户,拥有coder角色以及对应的两项权限。
用户在发送/main.jsp这个请求的时候,如果没有登录,将会被authc拦截器拦截到。请求会被重定向到规定的login.jsp页面。在login.jsp页面中,我将设计三个超链接,分别向后台发送登录认证请求。一个模拟发送正确的帐号密码,另外一个向后台发送错误的帐号密码。如果认证成功,就会跳转loginSuccess.jsp。登录成功后,我们再次发送/main.jsp这个请求,就可以直接请求到main.jsp页面中,因为authc拦截器发现你已经登录过了,所以放行本次请求,而非重定向到登录页面。第三个超链接用于退出,在shiro.ini配置文件中,将退出后的路径设置为login.jsp页面。
[main]
#用户退出后跳转指定JSP页面
logout.redirectUrl=/login.jsp
#若没有登录,则被authc拦截器重定向到login.jsp页面
authc.loginUrl = /login.jsp
[users]
jay = 123456,coder
[roles]
coder = code:insert,code:update
[urls]
#发送main请求需要经过认证拦截器authc
#如果用户没有登录,则重定向到login.jsp页面
/main.jsp = authc
#退出拦截器,注销当前用户
/logout = logout
五、编写JSP
首先先写一个login.jsp,设计一个超链接,向后台发送认证请求。
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title></title>
</head>
<body>
<h6>这里是login.jsp</h6>
<a href="<c:url value="/authen?username=jay&password=123456"/>">发送登录认证请求</a><br>
<a href="<c:url value="/authen?username=jay&password=12"/>">模拟发送错误的帐号密码请求</a><br>
</body>
</html>
下一步,编写一个main.jsp页面。它将用于测试authc拦截器是否起作用。
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>这里是main.jsp,欢迎来到shiro的世界</h1>
<a href="<c:url value="/logout"/>"><h3>退出</h3></a>
</body>
</html>
最后编写用户提示页面。登录成功与登录失败页面。
loginSuccess.jsp页面。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>登录成功</h1>
</body>
</html>
loginFailure.jsp页面。标个红,显眼点。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1 style="color: red">登录失败</h1>
</body>
</html>
六、测试
(1)首先启动项目,发送main.jsp。因为没有认证,所以会被shiro.ini强制重定向到login.jsp页面。
(2)在login.jsp页面中,发送一个错误的帐号密码,将会跳转登录失败页面。
(3)返回login.jsp页面,让我们发送一个正确的帐号密码给后台认证。
(4)认证成功后,我们再次请求一次main.jsp页面,结果是可以请求到的。
(5)在main.jsp页面中,点击退出,发送/logout请求。此请求将会被shiro的logout拦截器捕获,强制重定向到login.jsp页面。
(6)退出后发送main.jsp页面,将不能访问,还是被重定向到login.jsp页面。
测试结果如动图所示。
六、源码下载
本章节项目源码:点击我下载源码
----------------------------------------------------分割线-------------------------------------------------------
下一篇:第九节 Shiro标签原理分析
阅读更多:跟着大宇学Shiro目录贴