用户登录鉴权JWT代码实现

实现流程

1、用户请求登录

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

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

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

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

6、用户请求到达微服务

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

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

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

用户登录鉴权JWT代码实现_第1张图片

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

搭建父项目工程jwt-parent

创建项目

用户登录鉴权JWT代码实现_第2张图片

pom文件


<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>
    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.3.9.RELEASEversion>
        <relativePath/> 
    parent>
    <groupId>com.czxygroupId>
    <artifactId>jwt-parentartifactId>
    <version>0.0.1-SNAPSHOTversion>
    <packaging>pompackaging>
    <name>jwt-parentname>
    <description>Demo project for Spring Bootdescription>
<properties>
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
        <java.version>1.8java.version>
        <spring-cloud.version>Hoxton.SR10spring-cloud.version>
        <mybatis.starter.version>2.1.1mybatis.starter.version>
        <mapper.starter.version>1.2.3mapper.starter.version>
        <druid.starter.version>1.1.9druid.starter.version>
        <mysql.version>5.1.32mysql.version>
        <pageHelper.starter.version>1.2.3pageHelper.starter.version>
        <jjwt.version>0.7.0jjwt.version>
        <joda-time.version>2.9.6joda-time.version>
        <lombok.version>1.18.18lombok.version>
    properties>

    
    <dependencyManagement>
        <dependencies>
            
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-dependenciesartifactId>
                <version>${spring-cloud.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
            <dependency>
                <groupId>com.alibaba.cloudgroupId>
                <artifactId>spring-cloud-alibaba-dependenciesartifactId>
                <version>2.2.6.RELEASEversion>
                <type>pomtype>
                <scope>importscope>
            dependency>
            
            <dependency>
                <groupId>org.mybatis.spring.bootgroupId>
                <artifactId>mybatis-spring-boot-starterartifactId>
                <version>${mybatis.starter.version}version>
            dependency>
            
            <dependency>
                <groupId>tk.mybatisgroupId>
                <artifactId>mapper-spring-boot-starterartifactId>
                <version>${mapper.starter.version}version>
            dependency>
            <dependency>
                <groupId>com.github.pagehelpergroupId>
                <artifactId>pagehelper-spring-boot-starterartifactId>
                <version>${pageHelper.starter.version}version>
            dependency>
            
            <dependency>
                <groupId>com.alibabagroupId>
                <artifactId>druid-spring-boot-starterartifactId>
                <version>${druid.starter.version}version>
            dependency>
            <dependency>
                <groupId>mysqlgroupId>
                <artifactId>mysql-connector-javaartifactId>
                <version>${mysql.version}version>
            dependency>
            <dependency>
                <groupId>io.jsonwebtokengroupId>
                <artifactId>jjwtartifactId>
                <version>${jjwt.version}version>
            dependency>
            
            <dependency>
                <groupId>joda-timegroupId>
                <artifactId>joda-timeartifactId>
                <version>${joda-time.version}version>
            dependency>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starterartifactId>
            dependency>

            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-testartifactId>
            dependency>
            <dependency>
                <groupId>org.projectlombokgroupId>
                <artifactId>lombokartifactId>
                <version>${lombok.version}version>
            dependency>
        dependencies>
    dependencyManagement>

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


project>

启动Nacos注册中心

我这里启动是单节点模式

用户登录鉴权JWT代码实现_第3张图片

用户登录鉴权JWT代码实现_第4张图片

启动之后可以去页面访问Nacos,http://localhost:8845/nacos

其他模块搭建

创建jwt-common模块

创建项目

用户登录鉴权JWT代码实现_第5张图片

pom文件


<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-parentartifactId>
        <groupId>com.czxygroupId>
        <version>0.0.1-SNAPSHOTversion>
    parent>
    <modelVersion>4.0.0modelVersion>

    <artifactId>jwt-commonartifactId>

    <dependencies>
        <dependency>
            <groupId>io.jsonwebtokengroupId>
            <artifactId>jjwtartifactId>
        dependency>
        
        <dependency>
            <groupId>joda-timegroupId>
            <artifactId>joda-timeartifactId>
        dependency>
		<dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
        dependency>
    dependencies>
project>

加入工具类

项目结构
用户登录鉴权JWT代码实现_第6张图片

创建jwt-pojo模块

创建项目

用户登录鉴权JWT代码实现_第7张图片

POM文件


<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-parentartifactId>
        <groupId>com.czxygroupId>
        <version>0.0.1-SNAPSHOTversion>
    parent>
    <modelVersion>4.0.0modelVersion>

    <artifactId>jwt-pojoartifactId>
	<dependencies>
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
        dependency>
    dependencies>


project>

创建实体类

Goods(我这里是商品和用户)

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Goods {

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

User实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

    private Integer id;
    private String username;
    private String password;
    
}

搭建goods-search

功能分析

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

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

实现步骤:

1、pojo

2、controller

4、service

5、dao

创建项目

用户登录鉴权JWT代码实现_第8张图片

pom


<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>
    <parent>
        <groupId>com.czxygroupId>
        <artifactId>jwt-parentartifactId>
        <version>0.0.1-SNAPSHOTversion>
    parent>
    <artifactId>goods-searchartifactId>
    <packaging>jarpackaging>
    <name>goods-searchname>
    <description>Demo project for Spring Bootdescription>


  <dependencies>
        <dependency>
            <groupId>com.czxygroupId>
            <artifactId>jwt-pojo01artifactId>
            <version>0.0.1-SNAPSHOTversion>
        dependency>

        <dependency>
            <groupId>com.czxygroupId>
            <artifactId>jwt-common01artifactId>
            <version>0.0.1-SNAPSHOTversion>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
        dependency>
        




        <dependency>
            <groupId>com.alibaba.cloudgroupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
        dependency>
        
        <dependency>
            <groupId>com.alibaba.cloudgroupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
        dependency>
    dependencies>

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

project>

bootstrap.yml配置

spring:
  application:
    name: goods-service
  profiles:
    active: dev
  cloud:
    nacos:
      server-addr: localhost:8845
      config:
        file-extension: yaml
server:
  port: 7000

功能实现

模拟商品搜索功能
用户登录鉴权JWT代码实现_第9张图片

启动类

@SpringBootApplication
public class GoodsSearch01Application {
public static void main(String[] args) {
SpringApplication.run(GoodsSearch01Application.class, args);
}
}

功能测试

用户登录鉴权JWT代码实现_第10张图片

搭建user-service服务

功能分析

提供用户操作相关的接口

搭建项目

用户登录鉴权JWT代码实现_第11张图片

pom文件


<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>
   <parent>
      <groupId>com.czxygroupId>
      <artifactId>jwt-parentartifactId>
      <version>0.0.1-SNAPSHOTversion>
   parent>
   <artifactId>user-serviceartifactId>
   <packaging>jarpackaging>
   <name>user-servicename>
   <description>Demo project for Spring Bootdescription>

<dependencies>
        <dependency>
            <groupId>com.czxygroupId>
            <artifactId>jwt-pojo01artifactId>
            <version>0.0.1-SNAPSHOTversion>
        dependency>

        <dependency>
            <groupId>com.czxygroupId>
            <artifactId>jwt-common01artifactId>
            <version>0.0.1-SNAPSHOTversion>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
        dependency>
        




        <dependency>
            <groupId>com.alibaba.cloudgroupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
        dependency>
        
        <dependency>
            <groupId>com.alibaba.cloudgroupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
        dependency>
    dependencies>

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


project>

bootstrap.yml

spring:
  application:
    name: userservice
  profiles:
    active: dev
  cloud:
    nacos:
      server-addr: localhost:8848
      config:
        file-extension: yaml
server:
  port: 8000

功能实现

提供用户新增接口

用户登录鉴权JWT代码实现_第12张图片

启动类

@SpringBootApplication
public class UserService01Application {

public static void main(String[] args) {
    SpringApplication.run(UserService01Application.class, args);
}

}

功能测试

我这里拿的是PostMan测试,如果你们有自己的其他测试工具都可以,想学Postman使用的去我博客瞅瞅,有一篇

用户登录鉴权JWT代码实现_第13张图片

授权中心jwt-auth

授权中心的主要职责:

  • 用户鉴权:

    • 接收用户的登录请求,通过用户中心的接口进行校验,通过后生成JWT
    • 使用私钥生成JWT并返回
  • 服务鉴权:微服务间的调用不经过Zuul,会有风险,需要鉴权中心进行认证

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

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

创建授权中心

用户登录鉴权JWT代码实现_第14张图片

pom文件


<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>
    <parent>
        <groupId>com.czxygroupId>
        <artifactId>jwt-parentartifactId>
        <version>0.0.1-SNAPSHOTversion>
    parent>
    <artifactId>jwt-authartifactId>
    <packaging>jarpackaging>
    <name>jwt-authname>
    <description>Demo project for Spring Bootdescription>

   <dependencies>
        <dependency>
            <groupId>com.czxygroupId>
            <artifactId>jwt-pojo01artifactId>
            <version>0.0.1-SNAPSHOTversion>
        dependency>

        <dependency>
            <groupId>com.czxygroupId>
            <artifactId>jwt-common01artifactId>
            <version>0.0.1-SNAPSHOTversion>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
        dependency>
        
        
        
        
        
        <dependency>
            <groupId>com.alibaba.cloudgroupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
        dependency>
        
        <dependency>
            <groupId>com.alibaba.cloudgroupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
        dependency>
    dependencies>

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


project>

bootstrap.yml

spring:
  application:
    name: authservice
  profiles:
    active: dev
  cloud:
    nacos:
      server-addr: localhost:8845
      config:
        file-extension: yaml
server:
  port: 9000

功能实现

提供登录接口

用户登录鉴权JWT代码实现_第15张图片

启动类

@SpringBootApplication
public class JwtAuth01Application {

    public static void main(String[] args) {
        SpringApplication.run(JwtAuth01Application.class, args);
    }

}

功能测试

用户登录鉴权JWT代码实现_第16张图片

Zuul网关jwt-gateway

功能分析

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

用户登录鉴权JWT代码实现_第17张图片

pom文件


<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-parentartifactId>
        <groupId>com.czxygroupId>
        <version>0.0.1-SNAPSHOTversion>
    parent>
    <modelVersion>4.0.0modelVersion>

    <artifactId>jwt-zuulartifactId>

    <dependencies>
        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-gatewayartifactId>
        dependency>
        
        <dependency>
            <groupId>com.alibaba.cloudgroupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
        dependency>
    dependencies>

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

yml文件

server:
  port: 10010 # 网关端口
spring:
  application:
    name: gateway # 服务名称
  cloud:
    nacos:
      server-addr: localhost:8845 # nacos地址
    gateway:
      routes: # 网关路由配置
        - id: goods-service # 路由id,自定义,只要唯一即可
          # uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
          uri: lb://goodsservice # 路由的目标地址 lb就是负载均衡,后面跟服务名称
          predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
            - Path=/search/** # 这个是按照路径匹配,只要以/user/开头就符合要求
        - id: user-service
          uri: lb://userservice
          predicates:
            - Path=/user/**
        - id: auth-service
            uri: lb://authservice
            predicates:
              - Path=/auth/**

功能实现

  • 编写鉴权过滤器
@Component
@Order(-1)
public class JWTFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        String url = exchange.getRequest().getURI().getPath();
        System.out.println(url);
        // 1 判断URL
        if(url.toString().contains("login")){
            System.out.println("无需登录,直接放行");
            return chain.filter(exchange);
        }
        // 2.获取请求参数
//        MultiValueMap params = exchange.getRequest().getQueryParams();
//        // 3.获取authorization参数
//        String token = params.getFirst("authorization");

        List<String> tokens = exchange.getRequest().getHeaders().get("authorization");

        // 4判断是否为空
        if(tokens!=null&&(tokens.size()==1)){
            // 5 解析token
            Claims claims = JWTUtil.parseToken(tokens.get(0), "user");
            //6 判断解析是否成
            if(claims!=null){
                //7 成功了,放行
                return chain.filter(exchange);
            }
        }
        // 8.拦截
        // 8.1.禁止访问,设置状态码
        exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
        // 8.2.结束处理
        return exchange.getResponse().setComplete();

    }
}

功能测试

  • 商品搜索(未登录)

用户登录鉴权JWT代码实现_第18张图片

  • 用户新增(未登录)

用户登录鉴权JWT代码实现_第19张图片

  • 携带token,进行用户新增

用户登录鉴权JWT代码实现_第20张图片

这样我们就完成了鉴权!!

你可能感兴趣的:(Spring,spring,cloud,java,spring,boot)