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
- jwt-parent: Unified jar package version control
- jwt-pojo: entity class storage location
- jwt-common: the location where tool classes, constant classes, etc. are stored
- jwt-auth: authentication center
- goods-search: Goods search service, which exposes related interfaces of goods search
- 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
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
After startup, you can go to the page to visit Nacos, http://localhost:8845/nacos
Build other modules
Create jwt-common module
create project
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
Create jwt-pojo module
create project
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
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
startup class
@SpringBootApplication
public class GoodsSearch01Application {
public static void main(String[] args) {
SpringApplication.run(GoodsSearch01Application.class, args);
}
}
function test
Build user-service service
Functional Analysis
Provide user interface related to operation
build project
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
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
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
startup class
@SpringBootApplication
public class JwtAuth01Application {
public static void main(String[] args) {
SpringApplication.run(JwtAuth01Application.class, args);
}
}
function test
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
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)
- New user (not logged in)
- Carry the token to add users
In this way, we have completed the authentication! !