添加客户端注册接口

This commit is contained in:
柏码の讲师 2023-11-30 16:24:11 +08:00
parent 70d7cca7cd
commit 4695864db8
9 changed files with 169 additions and 9 deletions

View File

@ -54,6 +54,7 @@ public class SecurityConfiguration {
return http
.authorizeHttpRequests(conf -> conf
.requestMatchers("/api/auth/**", "/error").permitAll()
.requestMatchers("/monitor/**").permitAll()
.requestMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll()
.anyRequest().hasAnyRole(Const.ROLE_DEFAULT)
)

View File

@ -0,0 +1,23 @@
package com.example.controller;
import com.example.entity.RestBean;
import com.example.service.ClientService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/monitor")
public class ClientController {
@Resource
ClientService service;
@GetMapping("/register")
public RestBean<Void> registerClient(@RequestHeader("Authorization") String token) {
return service.verifyAndRegister(token) ?
RestBean.success() : RestBean.failure(401, "客户端注册失败请检查Token是否正确");
}
}

View File

@ -0,0 +1,18 @@
package com.example.entity.dto;
import com.baomidou.mybatisplus.annotation.TableName;
import com.example.entity.BaseData;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Date;
@Data
@TableName("db_client")
@AllArgsConstructor
public class Client implements BaseData {
Integer id;
String name;
String token;
Date registerTime;
}

View File

@ -1,6 +1,8 @@
package com.example.filter;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.example.entity.dto.Client;
import com.example.service.ClientService;
import com.example.utils.Const;
import com.example.utils.JwtUtils;
import jakarta.annotation.Resource;
@ -27,20 +29,37 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Resource
JwtUtils utils;
@Resource
ClientService service;
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String authorization = request.getHeader("Authorization");
DecodedJWT jwt = utils.resolveJwt(authorization);
if(jwt != null) {
UserDetails user = utils.toUser(jwt);
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
request.setAttribute(Const.ATTR_USER_ID, utils.toId(jwt));
String uri = request.getRequestURI();
if(uri.startsWith("/monitor")) {
if(!uri.endsWith("/register")) {
Client client = service.findClient(authorization);
if(client == null) {
response.setStatus(401);
return;
} else {
request.setAttribute(Const.ATTR_CLIENT, client);
}
}
filterChain.doFilter(request, response);
} else {
DecodedJWT jwt = utils.resolveJwt(authorization);
if(jwt != null) {
UserDetails user = utils.toUser(jwt);
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
request.setAttribute(Const.ATTR_USER_ID, utils.toId(jwt));
}
filterChain.doFilter(request, response);
}
filterChain.doFilter(request, response);
}
}

View File

@ -0,0 +1,9 @@
package com.example.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.entity.dto.Client;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ClientMapper extends BaseMapper<Client> {
}

View File

@ -0,0 +1,11 @@
package com.example.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.entity.dto.Client;
public interface ClientService extends IService<Client> {
String registerToken();
Client findClient(String token);
Client findClient(Integer id);
boolean verifyAndRegister(String token);
}

View File

@ -0,0 +1,77 @@
package com.example.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.entity.dto.Client;
import com.example.mapper.ClientMapper;
import com.example.service.ClientService;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.security.SecureRandom;
import java.util.Date;
import java.util.HashMap;
import java.util.Random;
@Slf4j
@Service
public class ClientServiceImpl extends ServiceImpl<ClientMapper, Client> implements ClientService {
private String registerToken = this.generateNewToken();
private final HashMap<Integer, Client> clientIdCache = new HashMap<>();
private final HashMap<String, Client> clientTokenCache = new HashMap<>();
@PostConstruct
public void initClientCache() {
this.list().forEach(this::addClientCache);
}
@Override
public Client findClient(Integer id) {
return clientIdCache.get(id);
}
@Override
public Client findClient(String token) {
return clientTokenCache.get(token);
}
@Override
public String registerToken() {
return registerToken;
}
@Override
public synchronized boolean verifyAndRegister(String token) {
if(this.registerToken.equals(token)) {
int id = this.randomClientId();
Client client = new Client(id, "未命名主机", token, new Date());
if(this.save(client)) {
registerToken = this.generateNewToken();
this.addClientCache(client);
return true;
}
log.warn("在注册客户端时Token验证成功但客户端数据插入失败请检查问题原因");
}
return false;
}
private void addClientCache(Client client) {
clientIdCache.put(client.getId(), client);
clientTokenCache.put(client.getToken(), client);
}
private int randomClientId(){
return new Random().nextInt(90000000) + 10000000;
}
private String generateNewToken() {
String CHARACTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
SecureRandom random = new SecureRandom();
StringBuilder sb = new StringBuilder(24);
for (int i = 0; i < 24; i++)
sb.append(CHARACTERS.charAt(random.nextInt(CHARACTERS.length())));
return sb.toString();
}
}

View File

@ -18,6 +18,7 @@ public final class Const {
public final static int ORDER_CORS = -102;
//请求自定义属性
public final static String ATTR_USER_ID = "userId";
public final static String ATTR_CLIENT = "client";
//消息队列
public final static String MQ_MAIL = "mail";
//用户角色

View File

@ -4,6 +4,7 @@
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/log" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />