支持登录
This commit is contained in:
21
src/main/java/com/xuxd/kafka/console/beans/Credentials.java
Normal file
21
src/main/java/com/xuxd/kafka/console/beans/Credentials.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package com.xuxd.kafka.console.beans;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author: xuxd
|
||||
* @date: 2023/5/14 19:37
|
||||
**/
|
||||
@Data
|
||||
public class Credentials {
|
||||
|
||||
public static final Credentials INVALID = new Credentials();
|
||||
|
||||
private String username;
|
||||
|
||||
private long expiration;
|
||||
|
||||
public boolean isInvalid() {
|
||||
return this == INVALID;
|
||||
}
|
||||
}
|
||||
13
src/main/java/com/xuxd/kafka/console/beans/LoginResult.java
Normal file
13
src/main/java/com/xuxd/kafka/console/beans/LoginResult.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package com.xuxd.kafka.console.beans;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author: xuxd
|
||||
* @date: 2023/5/14 20:44
|
||||
**/
|
||||
@Data
|
||||
public class LoginResult {
|
||||
|
||||
private String token;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.xuxd.kafka.console.beans.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author: xuxd
|
||||
* @date: 2023/5/14 18:59
|
||||
**/
|
||||
@Data
|
||||
public class LoginUserDTO {
|
||||
|
||||
private String username;
|
||||
|
||||
private String password;
|
||||
}
|
||||
21
src/main/java/com/xuxd/kafka/console/config/AuthConfig.java
Normal file
21
src/main/java/com/xuxd/kafka/console/config/AuthConfig.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package com.xuxd.kafka.console.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author: xuxd
|
||||
* @date: 2023/5/9 21:08
|
||||
**/
|
||||
@Data
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "auth")
|
||||
public class AuthConfig {
|
||||
|
||||
private boolean enable;
|
||||
|
||||
private String secret = "kafka-console-ui-default-secret";
|
||||
|
||||
private long expireHours;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.xuxd.kafka.console.controller;
|
||||
|
||||
import com.xuxd.kafka.console.beans.ResponseData;
|
||||
import com.xuxd.kafka.console.beans.dto.LoginUserDTO;
|
||||
import com.xuxd.kafka.console.config.AuthConfig;
|
||||
import com.xuxd.kafka.console.service.AuthService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* @author: xuxd
|
||||
* @date: 2023/5/11 18:54
|
||||
**/
|
||||
@RestController
|
||||
@RequestMapping("/auth")
|
||||
public class AuthController {
|
||||
|
||||
|
||||
private final AuthConfig authConfig;
|
||||
|
||||
private final AuthService authService;
|
||||
|
||||
public AuthController(AuthConfig authConfig, AuthService authService) {
|
||||
this.authConfig = authConfig;
|
||||
this.authService = authService;
|
||||
}
|
||||
|
||||
@GetMapping("/enable")
|
||||
public boolean enable() {
|
||||
return authConfig.isEnable();
|
||||
}
|
||||
|
||||
@PostMapping("/login")
|
||||
public ResponseData login(@RequestBody LoginUserDTO userDTO) {
|
||||
return authService.login(userDTO);
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,12 @@ package com.xuxd.kafka.console.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.xuxd.kafka.console.beans.dos.SysUserDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* @author: xuxd
|
||||
* @date: 2023/4/11 21:22
|
||||
**/
|
||||
@Mapper
|
||||
public interface SysUserMapper extends BaseMapper<SysUserDO> {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.xuxd.kafka.console.interceptor;
|
||||
|
||||
import com.xuxd.kafka.console.beans.Credentials;
|
||||
import com.xuxd.kafka.console.config.AuthConfig;
|
||||
import com.xuxd.kafka.console.utils.AuthUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.annotation.WebFilter;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author: xuxd
|
||||
* @date: 2023/5/9 21:20
|
||||
**/
|
||||
@Order(1)
|
||||
@WebFilter(filterName = "auth-filter", urlPatterns = {"/*"})
|
||||
@Slf4j
|
||||
public class AuthFilter implements Filter {
|
||||
|
||||
private final AuthConfig authConfig;
|
||||
|
||||
private final String TOKEN_HEADER = "X-Auth-Token";
|
||||
|
||||
private final String AUTH_URI_PREFIX = "/auth";
|
||||
|
||||
public AuthFilter(AuthConfig authConfig) {
|
||||
this.authConfig = authConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
|
||||
if (!authConfig.isEnable()) {
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
return;
|
||||
}
|
||||
HttpServletRequest request = (HttpServletRequest) servletRequest;
|
||||
HttpServletResponse response = (HttpServletResponse) servletResponse;
|
||||
String accessToken = request.getHeader(TOKEN_HEADER);
|
||||
|
||||
String requestURI = request.getRequestURI();
|
||||
if (requestURI.startsWith(AUTH_URI_PREFIX)) {
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
return;
|
||||
}
|
||||
if (StringUtils.isEmpty(accessToken)) {
|
||||
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||||
return;
|
||||
}
|
||||
|
||||
Credentials credentials = AuthUtil.parseToken(authConfig.getSecret(), accessToken);
|
||||
if (credentials.isInvalid()) {
|
||||
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||||
return;
|
||||
}
|
||||
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import com.xuxd.kafka.console.utils.ConvertUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
import javax.servlet.*;
|
||||
@@ -24,6 +25,7 @@ import java.util.Set;
|
||||
* @author xuxd
|
||||
* @date 2022-01-05 19:56:25
|
||||
**/
|
||||
@Order(100)
|
||||
@WebFilter(filterName = "context-set-filter", urlPatterns = {"/acl/*", "/user/*", "/cluster/*", "/config/*", "/consumer/*", "/message/*", "/topic/*", "/op/*", "/client/*"})
|
||||
@Slf4j
|
||||
public class ContextSetFilter implements Filter {
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.xuxd.kafka.console.service;
|
||||
|
||||
import com.xuxd.kafka.console.beans.ResponseData;
|
||||
import com.xuxd.kafka.console.beans.dto.LoginUserDTO;
|
||||
|
||||
/**
|
||||
* @author: xuxd
|
||||
* @date: 2023/5/14 19:00
|
||||
**/
|
||||
public interface AuthService {
|
||||
|
||||
ResponseData login(LoginUserDTO userDTO);
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.xuxd.kafka.console.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.xuxd.kafka.console.beans.Credentials;
|
||||
import com.xuxd.kafka.console.beans.LoginResult;
|
||||
import com.xuxd.kafka.console.beans.ResponseData;
|
||||
import com.xuxd.kafka.console.beans.dos.SysUserDO;
|
||||
import com.xuxd.kafka.console.beans.dto.LoginUserDTO;
|
||||
import com.xuxd.kafka.console.config.AuthConfig;
|
||||
import com.xuxd.kafka.console.dao.SysUserMapper;
|
||||
import com.xuxd.kafka.console.service.AuthService;
|
||||
import com.xuxd.kafka.console.utils.AuthUtil;
|
||||
import com.xuxd.kafka.console.utils.UUIDStrUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author: xuxd
|
||||
* @date: 2023/5/14 19:01
|
||||
**/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class AuthServiceImpl implements AuthService {
|
||||
|
||||
private final SysUserMapper userMapper;
|
||||
|
||||
private final AuthConfig authConfig;
|
||||
|
||||
public AuthServiceImpl(SysUserMapper userMapper, AuthConfig authConfig) {
|
||||
this.userMapper = userMapper;
|
||||
this.authConfig = authConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseData login(LoginUserDTO userDTO) {
|
||||
QueryWrapper<SysUserDO> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("username", userDTO.getUsername());
|
||||
SysUserDO userDO = userMapper.selectOne(queryWrapper);
|
||||
if (userDO == null) {
|
||||
return ResponseData.create().failed("用户名/密码不正确");
|
||||
}
|
||||
String encrypt = UUIDStrUtil.generate(userDTO.getPassword(), userDO.getSalt());
|
||||
if (!userDO.getPassword().equals(encrypt)) {
|
||||
return ResponseData.create().failed("用户名/密码不正确");
|
||||
}
|
||||
Credentials credentials = new Credentials();
|
||||
credentials.setUsername(userDO.getUsername());
|
||||
credentials.setExpiration(System.currentTimeMillis() + authConfig.getExpireHours() * 3600 * 1000);
|
||||
String token = AuthUtil.generateToken(authConfig.getSecret(), credentials);
|
||||
LoginResult loginResult = new LoginResult();
|
||||
loginResult.setToken(token);
|
||||
return ResponseData.create().data(loginResult).success();
|
||||
}
|
||||
}
|
||||
54
src/main/java/com/xuxd/kafka/console/utils/AuthUtil.java
Normal file
54
src/main/java/com/xuxd/kafka/console/utils/AuthUtil.java
Normal file
@@ -0,0 +1,54 @@
|
||||
package com.xuxd.kafka.console.utils;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.xuxd.kafka.console.beans.Credentials;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.Base64Utils;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* @author: xuxd
|
||||
* @date: 2023/5/14 19:34
|
||||
**/
|
||||
@Slf4j
|
||||
public class AuthUtil {
|
||||
|
||||
private static Gson gson = GsonUtil.INSTANCE.get();
|
||||
|
||||
public static String generateToken(String secret, Credentials info) {
|
||||
String json = gson.toJson(info);
|
||||
String str = json + secret;
|
||||
String signature = MD5Util.md5(str);
|
||||
return Base64Utils.encodeToString(json.getBytes(StandardCharsets.UTF_8)) + "." +
|
||||
Base64Utils.encodeToString(signature.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
public static boolean isToken(String token) {
|
||||
return token.split("\\.").length == 2;
|
||||
}
|
||||
|
||||
public static Credentials parseToken(String secret, String token) {
|
||||
if (!isToken(token)) {
|
||||
return Credentials.INVALID;
|
||||
}
|
||||
String[] arr = token.split("\\.");
|
||||
String infoStr = new String(Base64Utils.decodeFromString(arr[0]), StandardCharsets.UTF_8);
|
||||
String signature = new String(Base64Utils.decodeFromString(arr[1]), StandardCharsets.UTF_8);
|
||||
|
||||
String encrypt = MD5Util.md5(infoStr + secret);
|
||||
if (!encrypt.equals(signature)) {
|
||||
return Credentials.INVALID;
|
||||
}
|
||||
try {
|
||||
Credentials credentials = gson.fromJson(infoStr, Credentials.class);
|
||||
if (credentials.getExpiration() < System.currentTimeMillis()) {
|
||||
return Credentials.INVALID;
|
||||
}
|
||||
return credentials;
|
||||
} catch (Exception e) {
|
||||
log.error("解析token失败: {}", token, e);
|
||||
return Credentials.INVALID;
|
||||
}
|
||||
}
|
||||
}
|
||||
32
src/main/java/com/xuxd/kafka/console/utils/MD5Util.java
Normal file
32
src/main/java/com/xuxd/kafka/console/utils/MD5Util.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package com.xuxd.kafka.console.utils;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
* @author: xuxd
|
||||
* @date: 2023/5/14 20:25
|
||||
**/
|
||||
@Slf4j
|
||||
public class MD5Util {
|
||||
|
||||
public static MessageDigest getInstance() {
|
||||
try {
|
||||
MessageDigest md5 = MessageDigest.getInstance("MD5");
|
||||
return md5;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String md5(String str) {
|
||||
MessageDigest digest = getInstance();
|
||||
if (digest == null) {
|
||||
return null;
|
||||
}
|
||||
return new String(digest.digest(str.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user