当前位置:网站首页>Feign shares login information for request
Feign shares login information for request
2022-06-11 18:21:00 【_ Xiao_】
brief introduction
In development and some integration testing , The request invocation needs to be based on login , In the request, you need to carry the information obtained after login token Etc , This article explores this scenario
Background information description
The local experiment has three components :
- Login service : Provide user login and other services , After calling the login interface , Get sequenced token Information
- Business services : Business interface services , All access interfaces need login verification
- Test service : It can be regarded as an integration test project , First, access the login service to log in , obtain token Information , Then go to the business service
Login services and business services , It is not explained in this chapter , The login service and business service login authentication in this chapter are based on SaToken To build , You can refer to a previous blog article :Sa-Token Single sign on SSO Model 2 URL Redirect propagation session example
Without further ado , Here is the code description for testing the service
Maven Configuration information
Use in engineering spring Basis and feign, It's a separate project , The configuration is as follows :
<?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 https://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.7.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.self.growth</groupId>
<artifactId>integration-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>integration-test</name>
<description>integration-test</description>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>3.1.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
Engineering configuration information
We need to do some configuration , as follows :
test:
# User name and password for logging in to the service
login:
username: username
password: password
server:
# The request address of the business service
record:
url: http://localhost:9050
# Request address for login service
auth:
url: http://localhost:9000
spring:
main:
allow-bean-definition-overriding: true
Feign Client and interceptor configuration
The client of the login service is defined as follows :
package com.self.growth.integration.test.feign;
import com.self.growth.integration.test.vo.ResResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(
value = "UserClient",
url = "${test.server.auth.url}"
)
public interface UserClient {
@RequestMapping(method = RequestMethod.GET, value = "/sso/doLogin")
ResponseEntity<ResResult<Void>> login(@RequestParam("name") String name, @RequestParam("pwd") String pwd);
}
The above defines the client request url, And a login request , It uses ResponseEntity, Use this to get the returned header Information , And after logging in token It's going back to header Inside , This login service will be described in more detail later
Here you need a login Service, Process incoming requests , preservation token Information
package com.self.growth.integration.test.service;
import com.self.growth.integration.test.config.SaTokenContext;
import com.self.growth.integration.test.feign.UserClient;
import com.self.growth.integration.test.vo.ResResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import java.util.Objects;
@Slf4j
@Service
public class UserService {
private final UserClient userClient;
private final SaTokenContext saTokenContext;
@Value("${test.login.username}")
private String username;
@Value("${test.login.password}")
private String password;
private boolean isLogin = false;
public UserService(UserClient userClient, SaTokenContext saTokenContext) {
this.userClient = userClient;
this.saTokenContext = saTokenContext;
}
public void login() {
if (!isLogin) {
ResponseEntity<ResResult<Void>> res = userClient.login(username, password);
if (Objects.requireNonNull(res.getBody()).getCode() != 200) {
throw new RuntimeException(" User login failed ");
}
isLogin = true;
log.info(" Login successful ");
// The token Preservation
saTokenContext.refreshToken(res.getHeaders());
}
}
}
The logic of login should be simple and clear ,saTokenContext It can be seen that it is a single case , To preserve and provide Token Information , The specific code is as follows :
package com.self.growth.integration.test.config;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class SaTokenContext {
private String token;
private String key;
/** * Get... From the login return results Token Information * * be based on SaToken Login authentication framework , Processing ahead of time for the specific return * @param headers Login back to headers */
public void refreshToken(final HttpHeaders headers) {
final List<String> setCookie = headers.get("set-cookie");
assert setCookie != null;
if (setCookie.isEmpty()) {
return;
}
final String originCookie = setCookie.get(0);
key = originCookie.split(";")[0].split("=")[0];
token = originCookie.split(";")[0].split("=")[1];
}
public String getToken() {
return token;
}
public String getKey() {
return key;
}
}
After logging in above , We are right. Token Saved ,token Is used in subsequent requests , Add to request header
We use the global interception method here : The token Put it in the request head . The interceptors are as follows :
package com.self.growth.integration.test.config;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableFeignClients(basePackages = "com.self.growth.integration.test.feign")
public class FeignClientsConfigurationCustom implements RequestInterceptor {
private final SaTokenContext saTokenContext;
public FeignClientsConfigurationCustom(SaTokenContext saTokenContext) {
this.saTokenContext = saTokenContext;
}
@Override
public void apply(RequestTemplate template) {
final String token = saTokenContext.getToken();
if (token == null) {
return;
}
template.header(saTokenContext.getKey(), saTokenContext.getToken());
}
}
Last , Of business services Feign Client as follows , It's a simple one hello request :
package com.self.growth.integration.test.feign;
import com.self.growth.integration.test.vo.ResResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@FeignClient(
value = "RecordHelloFeign",
url = "${test.server.record.url}"
)
public interface RecordHelloClient {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
ResResult<String> hello();
}
Test verification
Writing test classes :
Here is the test record , Every request , Call the login service ( In the login service, there is a logic to not login after login , Just log in once )
package com.self.growth.integration.test;
import com.self.growth.integration.test.service.UserService;
import org.junit.jupiter.api.BeforeEach;
import org.springframework.beans.factory.annotation.Autowired;
public abstract class BaseServerTest {
@Autowired
private UserService userService;
@BeforeEach
public void login() {
userService.login();
}
}
Test access to business services :
package com.self.growth.integration.test.record;
import com.self.growth.integration.test.BaseServerTest;
import com.self.growth.integration.test.feign.RecordHelloClient;
import com.self.growth.integration.test.service.UserService;
import com.self.growth.integration.test.vo.ResResult;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@Slf4j
@SpringBootTest
public class RecordServerTest extends BaseServerTest {
@Autowired
private RecordHelloClient recordHelloClient;
@Test
public void helloTest() {
ResResult<String> res = recordHelloClient.hello();
log.info(res.toString());
Assertions.assertEquals(200, res.getCode());
}
}
give the result as follows :
2022-05-29 08:07:10.695 INFO 16348 --- [ main] c.s.g.i.test.service.UserService : Login successful
2022-05-29 08:07:11.959 INFO 16348 --- [ main] c.s.g.i.test.record.RecordServerTest : ResResult(data=hello: 1, code=200, msg=null)
summary
This article is about Feign Share login information for an attempt , The use is to define the interceptor to add token To the request header
边栏推荐
猜你喜欢
随机推荐
General terms in security field
最长严格递增子序列
Introduction to social engineering practice
Secret comment-----
HashSet集合
[c language] output students' names and scores in descending order of scores with structures
SISO Decoder for a General (n, N - 1) SPC Code (Supplementary section 3)
[MapReduce] a complete Mr program case teaches you how to package and run with idea
[Golang]力扣Leetcode - 349. 两个数组的交集(哈希表)
Understanding of distributed transactions
Explain AI accelerators in detail: GPU, DPU, IPU, TPU... There are infinite possibilities for AI acceleration schemes
[untitled]
Reading summary of nacos2.x source code
Spring 2021 daily question [week6 not finished]
DC-DC自举电容(BOOT)几个问题
LeetCode_ Prefix tree_ Medium_ 208. implement trie (prefix tree)
Oracle高级数据库复习
Sa-Token 单点登录 SSO模式二 URL重定向传播会话示例
Retrofit source code analysis
力扣32题最长有效括号







![[c language] compress strings and add markup characters](/img/b7/f7918f3ee0c409faffc70addd5ee65.png)
