diff --git a/itbaima-monitor-server/src/main/java/com/example/config/SecurityConfiguration.java b/itbaima-monitor-server/src/main/java/com/example/config/SecurityConfiguration.java index e61d41d..ec0afe5 100644 --- a/itbaima-monitor-server/src/main/java/com/example/config/SecurityConfiguration.java +++ b/itbaima-monitor-server/src/main/java/com/example/config/SecurityConfiguration.java @@ -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) ) diff --git a/itbaima-monitor-server/src/main/java/com/example/controller/ClientController.java b/itbaima-monitor-server/src/main/java/com/example/controller/ClientController.java new file mode 100644 index 0000000..817cd70 --- /dev/null +++ b/itbaima-monitor-server/src/main/java/com/example/controller/ClientController.java @@ -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 registerClient(@RequestHeader("Authorization") String token) { + return service.verifyAndRegister(token) ? + RestBean.success() : RestBean.failure(401, "客户端注册失败,请检查Token是否正确"); + } +} diff --git a/itbaima-monitor-server/src/main/java/com/example/entity/dto/Client.java b/itbaima-monitor-server/src/main/java/com/example/entity/dto/Client.java new file mode 100644 index 0000000..dedc9bd --- /dev/null +++ b/itbaima-monitor-server/src/main/java/com/example/entity/dto/Client.java @@ -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; +} diff --git a/itbaima-monitor-server/src/main/java/com/example/filter/JwtAuthenticationFilter.java b/itbaima-monitor-server/src/main/java/com/example/filter/JwtAuthenticationFilter.java index d110125..c17c4fa 100644 --- a/itbaima-monitor-server/src/main/java/com/example/filter/JwtAuthenticationFilter.java +++ b/itbaima-monitor-server/src/main/java/com/example/filter/JwtAuthenticationFilter.java @@ -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); } } diff --git a/itbaima-monitor-server/src/main/java/com/example/mapper/ClientMapper.java b/itbaima-monitor-server/src/main/java/com/example/mapper/ClientMapper.java new file mode 100644 index 0000000..fd26a5a --- /dev/null +++ b/itbaima-monitor-server/src/main/java/com/example/mapper/ClientMapper.java @@ -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 { +} diff --git a/itbaima-monitor-server/src/main/java/com/example/service/ClientService.java b/itbaima-monitor-server/src/main/java/com/example/service/ClientService.java new file mode 100644 index 0000000..22bce27 --- /dev/null +++ b/itbaima-monitor-server/src/main/java/com/example/service/ClientService.java @@ -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 { + String registerToken(); + Client findClient(String token); + Client findClient(Integer id); + boolean verifyAndRegister(String token); +} diff --git a/itbaima-monitor-server/src/main/java/com/example/service/impl/ClientServiceImpl.java b/itbaima-monitor-server/src/main/java/com/example/service/impl/ClientServiceImpl.java new file mode 100644 index 0000000..8eff490 --- /dev/null +++ b/itbaima-monitor-server/src/main/java/com/example/service/impl/ClientServiceImpl.java @@ -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 implements ClientService { + + private String registerToken = this.generateNewToken(); + + private final HashMap clientIdCache = new HashMap<>(); + private final HashMap 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(); + } +} diff --git a/itbaima-monitor-server/src/main/java/com/example/utils/Const.java b/itbaima-monitor-server/src/main/java/com/example/utils/Const.java index 941bf74..6e6882a 100644 --- a/itbaima-monitor-server/src/main/java/com/example/utils/Const.java +++ b/itbaima-monitor-server/src/main/java/com/example/utils/Const.java @@ -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"; //用户角色 diff --git a/itbaima-monitor.iml b/itbaima-monitor.iml index c90834f..0aa69c3 100644 --- a/itbaima-monitor.iml +++ b/itbaima-monitor.iml @@ -4,6 +4,7 @@ +