JSON Web Token(JWT)是一個很是輕巧的規範。這個規範容許咱們使用 JWT 在用戶和服務器之間傳遞安全可靠的信息。 咱們利用必定的編碼生成 Token,並在 Token 中加入一些非敏感信息,將其傳遞。html
開發工具:STS
Maven版本:apache-maven-3.5.2
java jdk 1.8
MySQL版本:5.7
系統:Windows10
配置Maven項目的pom.xml文件java
<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.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.3.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <groupId>cn.codepeople</groupId> <artifactId>SpringBoot-Shiro-JWT</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <log4j.version>1.2.17</log4j.version> <shiro.version>1.4.0</shiro.version> <com.alibaba.druid.version>1.1.10</com.alibaba.druid.version> <mysql.version>5.1.47</mysql.version> <mybatis.version>2.0.0</mybatis.version> <jwt.version>3.8.0</jwt.version> <swagger2.version>2.8.0</swagger2.version> </properties> <dependencies> <!-- spring boot --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-log4j2 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency> <!-- 引入shiro的spring整合框架 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>${shiro.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>${com.alibaba.druid.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>${mybatis.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>provided</scope> </dependency> <!-- Apache Commons --> <dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> <version>3.2.2</version> </dependency> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.6</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.54</version> </dependency> <!-- https://mvnrepository.com/artifact/com.auth0/java-jwt --> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>${jwt.version}</version> </dependency> <!-- swagger --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>${swagger2.version}</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>${swagger2.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> <!-- 打包時拷貝MyBatis的映射文件 --> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.*</include> </includes> <filtering>true</filtering> </resource> </resources> </build> </project>
JWTFilter.javamysql
/** * @Title: JWTFilter.java * @Package www.codepeople.cn.shiro * @Description: * Copyright: Copyright (c) 2019 www.codepeople.cn Inc. All rights reserved. * Website: www.codepeople.cn * 注意:本內容僅限於海南科瀾技術信息有限公司內部傳閱,禁止外泄以及用於其餘的商業目 * @Author 劉仁 * @DateTime 2019年4月1日 下午4:52:19 * @version V1.0 */ package www.codepeople.cn.shiro; import java.io.IOException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.RequestMethod; import lombok.extern.slf4j.Slf4j; /** * @ClassName: JWTFilter * @Description: * @Author 劉仁 * @DateTime 2019年4月1日 下午4:52:19 */ @Slf4j public class JWTFilter extends BasicHttpAuthenticationFilter{ /** * 判斷用戶是否想要登入。 * 檢測header裏面是否包含Authorization字段便可 */ @Override protected boolean isLoginAttempt(ServletRequest request, ServletResponse response) { HttpServletRequest req = (HttpServletRequest) request; String authorization = req.getHeader("Authorization"); log.info("判斷用戶是否想要登陸:{}",authorization); return authorization != null; } /** * */ @Override protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception { HttpServletRequest httpServletRequest = (HttpServletRequest) request; String authorization = httpServletRequest.getHeader("Authorization"); log.info("判斷用戶是否想要登陸x:{}",authorization); JWTToken token = new JWTToken(authorization); // 提交給realm進行登入,若是錯誤他會拋出異常並被捕獲 getSubject(request, response).login(token); // 若是沒有拋出異常則表明登入成功,返回true return true; } /** * 這裏咱們詳細說明下爲何最終返回的都是true,即容許訪問 * 例如咱們提供一個地址 GET /article * 登入用戶和遊客看到的內容是不一樣的 * 若是在這裏返回了false,請求會被直接攔截,用戶看不到任何東西 * 因此咱們在這裏返回true,Controller中能夠經過 subject.isAuthenticated() 來判斷用戶是否登入 * 若是有些資源只有登入用戶才能訪問,咱們只須要在方法上面加上 @RequiresAuthentication 註解便可 * 可是這樣作有一個缺點,就是不可以對GET,POST等請求進行分別過濾鑑權(由於咱們重寫了官方的方法),但實際上對應用影響不大 */ @Override protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { if (isLoginAttempt(request, response)) { try { executeLogin(request, response); } catch (Exception e) { response401(request, response); } } return true; } /** * 對跨域提供支持 */ @Override protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception { HttpServletRequest httpServletRequest = (HttpServletRequest) request; HttpServletResponse httpServletResponse = (HttpServletResponse) response; httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin"