User login authentication JWT code implementation

Implementation process

1. The user requests to log in

2. Zuul forwards the request to the authorization center and requests authorization

3. The verification of the authorization center is completed and the JWT certificate is issued

4. The client requests other functions and carries JWT

5. Zuul submits the jwt to the authorization center for verification, and releases it after passing

6. The user request arrives at the microservice

7. The microservice will hand over the jwt to the authentication center, and the authentication will analyze the user information at the same time

8. The authentication center returns user data to the microservice

9. The microservice processes the request and returns a response

insert image description here

  1. jwt-parent: Unified jar package version control
  2. jwt-pojo: entity class storage location
  3. jwt-common: the location where tool classes, constant classes, etc. are stored
  4. jwt-auth: authentication center
  5. goods-search: Goods search service, which exposes related interfaces of goods search
  6. user-service: user service, which exposes user operation-related interfaces, such as adding new users, etc.

Build the parent project project jwt-parent

create project

insert image description here

pom file

<?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>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.9.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>Hoxton.SR10</spring-cloud.version>
        <mybatis.starter.version>2.1.1</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.18.18</lombok.version>
    </properties>

    <!-- dependencyManagement
        这个标签一般用在父项目中,他不是导入jar包的标签,只是用来限定jar包版本的标签
        然后子项目依赖当前父项目,在子项目中导入需要的jar包坐标
        子项目无需填入版本号,完全由父项目控制
    -->
    <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>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.6.RELEASE</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.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
            </dependency>

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

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


</project>

Start the Nacos registration center

I start here in single node mode

insert image description here

After startup, you can go to the page to visit Nacos, http://localhost:8845/nacos

Build other modules

Create jwt-common module

create project

insert image description here

pom file

<?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>
        </dependency>
    </dependencies>
</project>

Add tools

project structure
insert image description here

Create jwt-pojo module

create project

insert image description here

POM file

<?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>
        </dependency>
    </dependencies>


</project>

Create entity classes

Goods (I am a product and a user here)

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Goods {
    
    

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

User entity class

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    
    

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

Build goods-search

Functional Analysis

1. The user is not logged in and can search for product information

2. goods-search is a product search service, receiving user page search requests

Implementation steps:

1、pojo

2、controller

4、service

5、dao

create project

[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-eOySx2Eu-1638864819939)(https://img-community.csdnimg.cn/images/2a05c7853ca340778adb749687c8c5bc.png "# left")]

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-pojo01</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>com.czxy</groupId>
            <artifactId>jwt-common01</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--mybatis-->
<!--        <dependency>-->
<!--            <groupId>org.mybatis.spring.boot</groupId>-->
<!--            <artifactId>mybatis-spring-boot-starter</artifactId>-->
<!--        </dependency>-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--nacos配置管理依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
    </dependencies>

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

</project>

bootstrap.yml configuration

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

function realization

Simulate product search function
insert image description here

startup class

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

function test

insert image description here

Build user-service service

Functional Analysis

Provide user interface related to operation

build project

insert image description here

pom file

<?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>com.czxy</groupId>
            <artifactId>jwt-pojo01</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>com.czxy</groupId>
            <artifactId>jwt-common01</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--mybatis-->
<!--        <dependency>-->
<!--            <groupId>org.mybatis.spring.boot</groupId>-->
<!--            <artifactId>mybatis-spring-boot-starter</artifactId>-->
<!--        </dependency>-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--nacos配置管理依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
    </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </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

function realization

Provide user interface

insert image description here

startup class

@SpringBootApplication
public class UserService01Application {

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

}

function test

I am taking the PostMan test here. If you have other testing tools of your own, you can go to my blog if you want to learn how to use Postman. There is an article

insert image description here

Authorization center jwt-auth

The main responsibilities of the authorization center:

  • User authentication:

    • Receive the user's login request, verify it through the interface of the user center, and generate JWT after passing
    • Generate JWT with private key and return
  • Service authentication: Calls between microservices do not pass through Zuul, there will be risks, and the authentication center needs to be authenticated

    • The principle is similar to user authentication, but the logic is slightly more complicated (we will not implement it here)

Because the behavior of generating jwt and parsing jwt will be used in other microservices in the future, so we will extract it into a tool. We aggregate the authentication center, a tool module, and a module that provides services

Create Authorization Center

]

pom file

<?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>com.czxy</groupId>
            <artifactId>jwt-pojo01</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>com.czxy</groupId>
            <artifactId>jwt-common01</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--mybatis-->
        <!--        <dependency>-->
        <!--            <groupId>org.mybatis.spring.boot</groupId>-->
        <!--            <artifactId>mybatis-spring-boot-starter</artifactId>-->
        <!--        </dependency>-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--nacos配置管理依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </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

function realization

Provide login interface

[External link image transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the image and upload it directly (img-aHkQ70Kc-1638864819942)(https://img-community.csdnimg.cn/images/3a02b1ec86db48f196b7973e8919d171.png "# left")]

startup class

@SpringBootApplication
public class JwtAuth01Application {
    
    

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

}

function test

[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-d65w1gZy-1638864819942)(https://img-community.csdnimg.cn/images/f876affd7be4453e935aee36561dfa46.png "# left")]

Zuul gateway jwt-gateway

Functional Analysis

  • 1. Filter all requests
  • 2. If the user initiates a login operation or a product search operation, release
  • 3. If the user initiates an operation on the user-service service, obtain and parse the token, if the token exists and is valid, release it; otherwise, respond to an error page

insert image description here

pom file

<?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-gateway</artifactId>
        </dependency>
        <!--nacos服务发现依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
    </dependencies>

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

yml file

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/**

function realization

  • Write an authentication filter
@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<String, String> 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();

    }
}

function test

  • Product search (not logged in)

insert image description here

  • New user (not logged in)

insert image description here

  • Carry the token to add users

[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-50TAfPZ9-1638864819944)(https://img-community.csdnimg.cn/images/a5fce17c51c64e26996afab2711de4ce.png "# left")]

In this way, we have completed the authentication! !

Guess you like

Origin blog.csdn.net/weixin_48143996/article/details/121772156