第八节 与WEB集成实例分析

x33g5p2x  于2021-12-18 转载在 其他  
字(7.1k)|赞(0)|评价(0)|浏览(204)

前言

      与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页面。

测试结果如动图所示。

六、源码下载

      本章节项目源码:点击我下载源码

相关文章