当前位置:网站首页>Distributed token
Distributed token
2022-06-25 15:24:00 【Running pig ZC】
Distributed token
background
When it comes to unified gateway entry , It is inevitable that multi system authentication mechanisms will be involved , If in the cluster scenario , There will be a problem , When a user logs in for the first time tomcat1 Yes , Interfaces go back and request other interfaces , Due to load balancing , The next request may be made at tomcat2 On , In this case, the verification fails , To solve this problem , So distributed token coming .

Realization principle

explain
First step : The user login , Verify the account and password successfully token Write to cookie in , And write the user information to redis
The second step : User requests other interfaces , With the successful login cookie
The third step : Server slave request Get to the cookie, analysis , Inquire about token Whether there is
Step four : There is , Continue business , non-existent , Returns an error
Realization
For convenience , This article uses annotations +aop The way to achieve .
Project structure

pom To configure
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
redisTemplate To configure
@Configuration
public class RedisTemplateConfig {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private Integer port;
@Value("${spring.redis.password}")
private String password;
@Bean
public JedisPoolConfig jedisPoolConfig(){
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setTestOnCreate(true);
poolConfig.setTestOnBorrow(true);
poolConfig.setTestOnReturn(true);
poolConfig.setTestWhileIdle(true);
return poolConfig;
}
@Bean
public JedisConnectionFactory jedisConnectionFactory(){
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(jedisPoolConfig());
jedisConnectionFactory.setHostName(host);
jedisConnectionFactory.setPort(port);
checkPasswordIfNull(jedisConnectionFactory);
return jedisConnectionFactory;
}
private void checkPasswordIfNull(JedisConnectionFactory jedisConnectionFactory){
if (!StringUtils.isEmpty(password)) {
jedisConnectionFactory.setPassword(password);
}
}
@Bean
public RedisTemplate<Object, Object> redisTemplate() {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(jedisConnectionFactory());
template.setValueSerializer(new StringRedisSerializer());
template.setHashValueSerializer(new StringRedisSerializer());
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.afterPropertiesSet();
return template;
}
}
Custom annotation
/** * Whether the interface needs a login annotation */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NeedLogin {
String value() default "";
}
Slice verification logic
/** * Whether the interface requires login aspect verification */
@Component
@Aspect
@Slf4j
public class VerificationAspect {
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@Pointcut("@annotation(com.zcc.distributetoken.anootation.NeedLogin)")
public void verification() {
}
@Around("verification()")
public Object verification(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
HttpServletRequest request = (HttpServletRequest) requestAttributes
.resolveReference(RequestAttributes.REFERENCE_REQUEST);
Cookie[] cookies = request.getCookies();
if (cookies == null || cookies.length == 0){
throw new NotLoginException(" The user is not logged in ");
}
for (Cookie cookie : cookies) {
if (Constant.TOKEN.equals(cookie.getName())){
if (null != redisTemplate.opsForValue().get(cookie.getValue())){
return proceedingJoinPoint.proceed();
}
}
}
throw new NotLoginException(" The user is not logged in ");
}
}
Global exception handling
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
@ExceptionHandler(value = NotLoginException.class)
@ResponseBody
public Result<?> notLoginExceptionHandler(HttpServletRequest req, NotLoginException e){
log.error(" The user is not logged in ");
return Result.error(CODE_SYS_ERROR, e.getMessage());
}
}
Test code
@RestController
public class TestController {
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@RequestMapping("login")
public Result<?> login(HttpServletRequest request, HttpServletResponse response){
String token = IdUtil.simpleUUID();
redisTemplate.opsForValue().set(token, " User information ", 30 * 60, TimeUnit.SECONDS);
Cookie c = new Cookie(Constant.TOKEN, token);
response.addCookie(c);
return Result.success("OK");
}
/** * The interface that needs to verify permissions add NeedLogin Annotations can be * @return */
@RequestMapping("ppp")
@NeedLogin
public Result<?> ppp(){
redisTemplate.opsForValue().set("name", "dsdsdds");
return Result.success("OK");
}
}
Optimize
Consider encapsulating the above code into starter, It is convenient for other business lines in the company to use together , Reduce access costs , Easy to maintain .
summary
This paper mainly introduces the distributed token The background of , To solve what problems , Evolution , And how to implement a plug-in distributed token System
Code address
https://github.com/18310781743/distribute-token
边栏推荐
- Two advanced playing methods of QT signal and slot
- Function of getinstance() method
- The difference between sizeof and strlen
- Graphic control and layout basis of R visualization
- JSON module dictionary and string conversion
- The last glory of the late Ming Dynasty - the battle of Korea
- 在打新债开户证券安全吗,需要什么准备
- 0703 interface automation - MySQL database connection, encapsulation, adding database verification in use cases
- Shared memory synchronous encapsulation
- Judging the number of leap years from 1 to N years
猜你喜欢

Afterword of Parl intensive learning 7-day punch in camp

Summary of four parameter adjustment methods for machine learning
![[paper notes] overview of case segmentation](/img/93/57ad42e0c058b7d5fd1b4066678707.jpg)
[paper notes] overview of case segmentation

SPARQL learning notes of query, an rrdf query language

Paddlepaddle paper reproduction course biggan learning experience

Dynamic memory allocation

C language escape character and its meaning

Solution of push code failure in idea

Esp8266 building smart home system

Stack and queue
随机推荐
Sequential programming 1
Review of arrays and pointers triggered by a topic
New title of PTA
0706-- replace fields in the use case, such as mobile phone number or ID
JSON module dictionary and string conversion
How to deal with mining process
Automatic correlation between QT signal and slot
Pytorch | how to save and load pytorch models?
网上办理股票开户安全吗?
Arithmetic operations and expressions
The difference between sizeof and strlen
Installing QT plug-in in Visual Studio
Kali SSH Remote Login
Is it safe to open a stock account online?
Vs2019 scanf error
Common classes in QT
Work of the first week
Qt: Pro project file
[paper notes] semi supervised object detection (ssod)
Function of getinstance() method