Bootstrap

鉴权系统搭建(JWT)

1.前言

在上一篇文章的基础上我们学习搭建JWT的鉴权系统
1.0.JWT交互流程
上一篇:JWT使用
1.4.JWT交互流程
流程图:
在这里插入图片描述

步骤翻译:

• 1、用户登录

• 2、服务的认证,通过后根据secret生成token

• 3、将生成的token返回给用户

• 4、用户每次请求携带token

• 5、服务端利解读jwt签名,判断签名有效后,从Payload中获取用户信息

• 6、处理请求,返回响应结果

因为JWT签发的token中已经包含了用户的身份信息,并且每次请求都会携带,这样服务的就无需保存用户信息,甚至无需去数据库查询,就能知道用户身份,完全符合了Rest的无状态规范。

1.5.结合Zuul的鉴权流程

我们逐步演进系统架构设计。需要注意的是:secret是签名的关键,因此一定要保密,我们放到鉴权中心保存,其它任何服务中都不能获取secret。

在微服务架构中,我们可以把服务的鉴权操作放到网关中,将未通过鉴权的请求直接拦截,如图:

在这里插入图片描述
流程图解:

  1. 第一个流程:用户点击登录—>请求授权中心颁发jwt凭证
  2. 第二个流程:用户的每次请求都携带jwt凭证—>zuul判断jwt是否正确

• 1、用户请求登录

• 2、Zuul将请求转发到授权中心,请求授权

• 3、授权中心校验完成,颁发JWT凭证

• 4、客户端请求其它功能,携带JWT

• 5、Zuul将jwt交给授权中心校验,通过后放行

• 6、用户请求到达微服务

• 7、微服务将jwt交给鉴权中心,鉴权同时解析用户信息

• 8、鉴权中心返回用户数据给微服务

• 9、微服务处理请求,返回响应

2. 项目整体架构

以下项目要搭建出这几个模块,有的话直接搭建认证模块

在这里插入图片描述

  • jwt-parent:统一jar包版本控制
  • jwt-eureka:eureka注册中心
  • user-service:用户服务,对外暴露用户操作相关接口,如新增用户等
  • jwt-auth:认证中心
  • jwt-pojo:实体类存放位置
  • jwt-common:工具类、常量类等存放的位置
  • goods-search:商品搜索服务,对外暴露商品搜索相关接口

结论:

  1. 项目的整体架构方式
  2. 搭建认证+授权中心
  3. 通过zuul进行权限过滤

3. 搭建父工程jwt-parent

3.1 创建项目

在这里插入图片描述

3.2 pom

 <?xml version="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.0</modelVersion>
    <modules>
        <module>jwt-eureka</module>
        <module>jwt-common</module>
        <module>jwt-pojo</module>
    </modules>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.czxy</groupId>
    <artifactId>jwt-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>jwt-parent</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.M3</spring-cloud.version>
        <mybatis.starter.version>1.3.2</mybatis.starter.version>
        <mapper.starter.version>1.2.3</mapper.starter.version>
        <druid.starter.version>1.1.9</druid.starter.version>
        <mysql.version>5.1.32</mysql.version>
        <pageHelper.starter.version>1.2.3</pageHelper.starter.version>
        <jjwt.version>0.7.0</jjwt.version>
        <joda-time.version>2.9.6</joda-time.version>
        <lombok.version>1.16.22</lombok.version>
    </properties>


    <dependencyManagement>
        <dependencies>
            <!-- springCloud -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- mybatis启动器 -->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis.starter.version}</version>
            </dependency>
            <!-- 通用Mapper启动器 -->
            <dependency>
                <groupId>tk.mybatis</groupId>
                <artifactId>mapper-spring-boot-starter</artifactId>
                <version>${mapper.starter.version}</version>
            </dependency>
            <dependency>
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper-spring-boot-starter</artifactId>
                <version>${pageHelper.starter.version}</version>
            </dependency>
            <!-- druid启动器 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>${druid.starter.version}</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>
            <dependency>
                <groupId>io.jsonwebtoken</groupId>
                <artifactId>jjwt</artifactId>
                <version>${jjwt.version}</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/joda-time/joda-time -->
            <dependency>
                <groupId>joda-time</groupId>
                <artifactId>joda-time</artifactId>
                <version>${joda-time.version}</version>
            </dependency>

            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>



    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

添加一段配置,用来启动管理我们服务,写下文的时候突然发现没配,回来写上【捂脸】

    <option name="configurationTypes">
      <set>
        <option value="SpringBootApplicationConfigurationType" />
      </set>
    </option>

在这里插入图片描述

4. 搭建Eureka注册中心

4.1 创建项目

注:网速好了用Spring脚手架,我用的maven模块搭的
在这里插入图片描述

4.2 pom

<?xml version="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.0</modelVersion>
    <parent>
        <groupId>com.czxy</groupId>
        <artifactId>jwt-parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <groupId>com.czxy</groupId>
    <artifactId>jwt-eureka</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>jwt-eureka</name>
    <description>Demo project for Spring Boot</description>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

4.3 yml配置

server:
  port: 10086 #eureka端口号

spring:
  application:
    name: eureka-server #eureka服务的名字

eureka:
  server:
    enable-self-preservation: true # Eureka自我保护机制,true打开/false禁用,默认打开状态,建议生产环境打开此配置。
    eviction-interval-timer-in-ms: 5000 # 修改检查失效服务的时间
  client:
    fetch-registry: true # 定期的更新客户端的服务清单,以保证服务访问的正确性
    register-with-eureka: true # 是否将自己注册为服务
    service-url:
      defaultZone: http://127.0.0.1:${server.port}/eureka # eureka服务的开放地址

4.4 测试

在这里插入图片描述

5.准备工作

5.1 创建jwt-common模块

5.1.1 创建项目

在这里插入图片描述

5.1.2 pom

 <?xml version="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">
    <parent>
        <artifactId>jwt-parent</artifactId>
        <groupId>com.czxy</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>jwt-common</artifactId>

    <dependencies>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/joda-time/joda-time -->
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>

    </dependencies>
</project>

5.1.3 加入工具类

在这里插入图片描述

jwt-util

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.joda.time.DateTime;

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;

/**
 * jwt工具类
 */
public class JWTUtil {


    /**
     * 获取token中的参数
     *
     * @param token
     * @return
     */
    public static Claims parseToken(String token,String key) {
        if ("".equals(token)) {
            return null;
        }

        try {
            return Jwts.parser()
                    .setSigningKey(DatatypeConverter.parseBase64Binary(key))
                    .parseClaimsJws(token).getBody();
        } catch (Exception ex) {
            return null;
        }
    }

    /**
     * 生成token
     *
     * @param userId
     * @return
     */
    public static String createToken(Integer userId,String key, int expireMinutes) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

        long nowMillis = System.currentTimeMillis();

        //生成签名密钥
        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(key);

        Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());

        //添加构成JWT的参数
        JwtBuilder builder = Jwts.builder()
//                .setHeaderParam("type", "JWT")
//                .setSubject(userId.toString())
                .claim("userId", userId) // 设置载荷信息
                .setExpiration(DateTime.now().plusMinutes(expireMinutes).toDate())// 设置超时时间
                .signWith(signatureAlgorithm, signingKey);

        //生成JWT
        return builder.compact();
    }
}

baseutil 这个主要是浏览器请求服务器,服务器接收请求作出的回执信息


/**
 * 使用了lombok提供的@Data注解可以免写getset toString方法
 * @Author ZhangLe
 * @Date 2018/12/14 10:04
 */
@Data
public class BaseResult {
    private Integer errno;//0成功,1失败
    private String errmsg;//提示内容
    private Object data;//返回的内容
    public BaseResult(Integer errno, String errmsg,Object object) {
        this.errno = errno;
        this.errmsg = errmsg;
        this.data=object;
    }
}

5.2 创建jwt-pojo模块

5.2.1 创建项目

在这里插入图片描述

5.2.2 POM

 <?xml version="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">
    <parent>
        <artifactId>jwt-parent</artifactId>
        <groupId>com.czxy</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>jwt-pojo</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>

5.2.3 创建实体类

Goods商品实体类


/**
 * 测试对象
 */
@Data
public class Goods {

    private Integer skuid;
    private String goodsName;
    private Double price;

    public Goods() {
    }

    public Goods(Integer skuid, String goodsName, Double price) {
        this.skuid = skuid;
        this.goodsName = goodsName;
        this.price = price;
    }
 
}

User实体类


/**
 * @Author ZhangLe
 * @Date 2018/12/17 17:30
 */
@Data
public class User {
    private Integer id;
    private String username;
    private String password;

    public User() {
    }

    public User(Integer id, String username, String password) {

        this.id = id;
        this.username = username;
        this.password = password;
    }

}

6. 搭建goods-search

6.1 功能分析

1、用户未登陆状态,可以搜索商品信息

2、goods-search为商品搜索服务,接收用户页面搜索请求

实现步骤:

1、pojo

2、controller

4、service

5、dao

6.2 创建项目

在这里插入图片描述

6.3 pom

<?xml version="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.0</modelVersion>
    <parent>
        <groupId>com.czxy</groupId>
        <artifactId>jwt-parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>goods-search</artifactId>
    <packaging>jar</packaging>
    <name>goods-search</name>
    <description>Demo project for Spring Boot</description>


    <dependencies>
        <dependency>
            <groupId>com.czxy</groupId>
            <artifactId>jwt-pojo</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>com.czxy</groupId>
            <artifactId>jwt-common</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

6.4 yml配置

server:
  port: 8084
spring:
  application:
    name: goods-search
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka
  instance:
    prefer-ip-address: true
    ip-address: 127.0.0.1
    instance-id: ${eureka.instance.ip-address}.${server.port}
    lease-renewal-interval-in-seconds: 3
    lease-expiration-duration-in-seconds: 10

6.5 功能实现

  1. 开启服务发现

在这里插入图片描述
2. 提供商品搜索功能
在这里插入图片描述

 
/**
 * @Author ZhangLe
 * @Date 2018/12/17 17:51
 */
@RestController
@RequestMapping("/search")
public class GoodsSearchController {
    /**
     * 我们使用伪造数据 知道是查出来的就行了 这里为了模拟Token
     * @return
     */
    @GetMapping
    public BaseResult GoodsSearch(){

        ArrayList<Goods> goods = new ArrayList<>();
        goods.add(new Goods(1,"huawei",1.0));
        goods.add(new Goods(2,"xiaomi",1.0));
        goods.add(new Goods(3,"meizu",1.0));

        BaseResult baseResult = new BaseResult(0,null,goods);

        return baseResult;
    }

}

6.6 功能测试

http://localhost:8084/search
在这里插入图片描述

7 搭建user-service服务

7.1 功能分析

  • 1、提供用户操作相关的接口

7.2 搭建项目

还是推荐Spring脚手架搭建
在这里插入图片描述

7.3 pom

<?xml version="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.0</modelVersion>
    <parent>
        <groupId>com.czxy</groupId>
        <artifactId>jwt-parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>user-service</artifactId>
    <packaging>jar</packaging>
    <name>user-service</name>
    <description>Demo project for Spring Boot</description>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.czxy</groupId>
            <artifactId>jwt-common</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.czxy</groupId>
            <artifactId>jwt-pojo</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

7.4 yml

server:
  port: 8086
spring:
  application:
    name: user-service
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka
  instance:
    prefer-ip-address: true
    ip-address: 127.0.0.1
    instance-id: ${eureka.instance.ip-address}.${server.port}
    lease-renewal-interval-in-seconds: 3
    lease-expiration-duration-in-seconds: 10

7.5 功能实现

  • 提供用户新增接口
    在这里插入图片描述
/**
 * @Author ZhangLe
 * @Date 2018/12/17 18:45
 */
@RestController
@RequestMapping("user")
public class UserController {
    @PostMapping
    public BaseResult saveUser(User user){

        System.out.println("新增用户"+user);
        return new BaseResult(0,"success",null);

    }
}

7.6 功能测试

http://localhost:8086/user在这里插入图片描述

8. 授权中心jwt-auth

授权中心的主要职责:

• 用户鉴权:

– 接收用户的登录请求,通过用户中心的接口进行校验,通过后生成JWT

– 使用私钥生成JWT并返回

• 服务鉴权:微服务间的调用不经过Zuul,会有风险,需要鉴权中心进行认证

– 原理与用户鉴权类似,但逻辑稍微复杂一些(此处我们不做实现)

因为生成jwt,解析jwt这样的行为以后在其它微服务中也会用到,因此我们会抽取成工具。我们把鉴权中心进行聚合,一个工具module,一个提供服务的module

8.1 创建授权中心

在这里插入图片描述

8.2 pom

<?xml version="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.0</modelVersion>
    <parent>
        <groupId>com.czxy</groupId>
        <artifactId>jwt-parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>jwt-auth</artifactId>
    <packaging>jar</packaging>
    <name>jwt-auth</name>
    <description>Demo project for Spring Boot</description>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.czxy</groupId>
            <artifactId>jwt-common</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.czxy</groupId>
            <artifactId>jwt-pojo</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

8.3 yml

server:
  port: 8082
spring:
  application:
    name: jwt-auth
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka
  instance:
    prefer-ip-address: true
    ip-address: 127.0.0.1
    instance-id: ${eureka.instance.ip-address}.${server.port}
    lease-renewal-interval-in-seconds: 3
    lease-expiration-duration-in-seconds: 10

8.4 功能实现

  • 提供登录接口
    在这里插入图片描述

8.5 功能测试

http://localhost:8082/login?username=admin&password=admin

在这里插入图片描述

9. Zuul网关jwt-zuul

9.1 功能分析

  • 1、对所有请求进行过滤
  • 2、如果用户发起的是登录操作或者是商品搜索操作,放行
  • 3、如果用户发起的是对user-service服务的操作,获取并解析token,如果token存在且有效,放行;否则响应错误页面

9.2 搭建jwt-zuul项目

在这里插入图片描述

9.3 pom

<?xml version="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">
    <parent>
        <artifactId>jwt-parent</artifactId>
        <groupId>com.czxy</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>jwt-zuul</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>com.czxy</groupId>
            <artifactId>jwt-common</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

9.4 yml

server:
  port: 10010
spring:
  application:
    name: jwt-zuul
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka
  instance:
    prefer-ip-address: true
    ip-address: 127.0.0.1
    instance-id: ${eureka.instance.ip-address}.${server.port}
    lease-renewal-interval-in-seconds: 3
    lease-expiration-duration-in-seconds: 10
ribbon:
  ConnectTimeout: 300
  ReadTimeout: 1000
  OkToRetryOnAllOperations: true
  MaxAutoRetriesNextServer: 2
  MaxAutoRetries: 1
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 6000

9.5 功能实现

  • 配置服务发现和开启zuul网关功能
    在这里插入图片描述
/**
 * @Author ZhangLe
 * @Date 2018/12/18 8:34
 */
@SpringBootApplication
@EnableDiscoveryClient
@EnableZuulProxy
public class UserZuulApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserZuulApplication.class,args);

    }
}

  • 编写鉴权过滤器
  • 继承网关监听器ZuulFilter重写父类方法
    在这里插入图片描述
    重写这个方法内容在这里插入图片描述

这段代码建议仔细看看run()方法

package com.czxy.config;

import com.czxy.util.JWTUtil;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import io.jsonwebtoken.Claims;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;


/**
 * @Author ZhangLe
 * @Date 2018/12/18 8:37
 */
@Component
public class JWTFilter extends ZuulFilter {


    @Override
    public String filterType() {

        System.out.println("前置过滤器");
        return "pre";
    }

    @Override
    public int filterOrder() {
        System.out.println("优先级别,数字越小,优先级越高");
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        System.out.println("是否执行过滤器,true,执行");
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext currentContext = RequestContext.getCurrentContext();
        //获取header
        HttpServletRequest request = currentContext.getRequest();
        //获取请求的url
        String url = request.getRequestURL().toString();
        if (url.indexOf("/login")>0 || url.indexOf("/search") > 0){
            System.out.println("登录");
            return null;
        }
        String key = "";
        if (url.indexOf("user-service") != -1){
            key = "user";
            String token = request.getHeader("authorizztion");
            if (token != null){
                Claims claims = JWTUtil.parseToken(token, key);
                if (claims != null){
                    currentContext.addZuulRequestHeader("authorizztion",token);
                    return null;
                }
            }
        }
        currentContext.setSendZuulResponse(false);//终止运行
        currentContext.setResponseStatusCode(401);
        currentContext.setResponseBody("{'flag':false,'message':'未登录'}");
        currentContext.getResponse().setContentType("text/html;charset=UTF-8");
        return null;
    }
}

9.6 功能测试

  • 商品搜索
    http://localhost:10010/goods-search/search在这里插入图片描述

  • 用户新增(未登录)

http://localhost:10010/user-service/user

未携带token
在这里插入图片描述

  • 用户登录

  • http://localhost:10010/jwt-auth/login?username=admin&password=admin
    在这里插入图片描述

  • 携带token,进行用户新增

  • http://localhost:10010/user-service/user
    注:必须先登录,获取到token才能用户新增

token

eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjEsImV4cCI6MTU0NTA5NzM2M30.ouywUb_0KG4H132AcjPArSHkLXos1ceafGiNMpgdSdo

写了token,Authorizztion大小写无所谓
在这里插入图片描述
番外
网关执行流程
在这里插入图片描述
用户新增
在这里插入图片描述

祝你幸福
送你一首歌《直到遇见了你我只喜欢你》陈柯宇
我去商场偶然听见,记住了高潮部分歌词 然后搜了出来,第一次听
附图:中国地图(看看以后自己会去哪,下个月写点面试经验,给以后的自己看)
在这里插入图片描述

;