basic user auth
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
package com.xuxd.kafka.console.beans;
|
||||
|
||||
public class KafkaConsoleException extends RuntimeException{
|
||||
public KafkaConsoleException(String msg){
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import lombok.Setter;
|
||||
**/
|
||||
public class ResponseData<T> {
|
||||
|
||||
public static final int SUCCESS_CODE = 0, FAILED_CODE = -9999;
|
||||
public static final int SUCCESS_CODE = 0, TOKEN_ILLEGAL = -5000, FAILED_CODE = -9999;
|
||||
|
||||
public static final String SUCCESS_MSG = "success", FAILED_MSG = "failed";
|
||||
|
||||
@@ -58,6 +58,12 @@ public class ResponseData<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResponseData<T> failed(int code) {
|
||||
this.code = code;
|
||||
this.msg = FAILED_MSG;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResponseData<T> failed(String msg) {
|
||||
this.code = FAILED_CODE;
|
||||
this.msg = msg;
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.xuxd.kafka.console.beans.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface RequiredAuthorize {
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.xuxd.kafka.console.beans.dos;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.xuxd.kafka.console.beans.enums.Role;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("t_devops_user")
|
||||
public class DevOpsUserDO {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private String username;
|
||||
|
||||
private String password;
|
||||
|
||||
private Role role;
|
||||
|
||||
private boolean delete;
|
||||
|
||||
private Date createTime;
|
||||
|
||||
private Date updateTime;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.xuxd.kafka.console.beans.dto.user;
|
||||
|
||||
import com.xuxd.kafka.console.beans.enums.Role;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AddUserDTO {
|
||||
private String username;
|
||||
private String password;
|
||||
private Role role;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.xuxd.kafka.console.beans.dto.user;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ListUserDTO {
|
||||
private Long id;
|
||||
private String username;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.xuxd.kafka.console.beans.dto.user;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class LoginDTO {
|
||||
private String username;
|
||||
private String password;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.xuxd.kafka.console.beans.dto.user;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class PasswordDTO {
|
||||
private Long userId;
|
||||
private String password;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.xuxd.kafka.console.beans.dto.user;
|
||||
|
||||
import com.xuxd.kafka.console.beans.enums.Role;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class UpdateUserDTO {
|
||||
private String username;
|
||||
private String password;
|
||||
private Role role;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.xuxd.kafka.console.beans.enums;
|
||||
|
||||
public enum Role {
|
||||
developer,
|
||||
manager
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.xuxd.kafka.console.beans.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.xuxd.kafka.console.beans.enums.Role;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class DevOpsUserVO {
|
||||
private Long id;
|
||||
private String username;
|
||||
private Role role;
|
||||
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
|
||||
private Date createTime;
|
||||
}
|
||||
16
src/main/java/com/xuxd/kafka/console/beans/vo/LoginVO.java
Normal file
16
src/main/java/com/xuxd/kafka/console/beans/vo/LoginVO.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package com.xuxd.kafka.console.beans.vo;
|
||||
|
||||
import com.xuxd.kafka.console.beans.enums.Role;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class LoginVO {
|
||||
private String token;
|
||||
private Role role;
|
||||
}
|
||||
@@ -2,15 +2,20 @@ package com.xuxd.kafka.console.boot;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.xuxd.kafka.console.beans.dos.ClusterInfoDO;
|
||||
import com.xuxd.kafka.console.beans.dos.DevOpsUserDO;
|
||||
import com.xuxd.kafka.console.config.KafkaConfig;
|
||||
import com.xuxd.kafka.console.dao.ClusterInfoMapper;
|
||||
import com.xuxd.kafka.console.dao.DevOpsUserMapper;
|
||||
import com.xuxd.kafka.console.utils.ConvertUtil;
|
||||
import java.util.List;
|
||||
|
||||
import com.xuxd.kafka.console.utils.Md5Utils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.xuxd.kafka.console.boot;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.xuxd.kafka.console.beans.dos.DevOpsUserDO;
|
||||
import com.xuxd.kafka.console.beans.enums.Role;
|
||||
import com.xuxd.kafka.console.dao.DevOpsUserMapper;
|
||||
import com.xuxd.kafka.console.utils.Md5Utils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class InitSuperDevOpsUser implements SmartInitializingSingleton {
|
||||
|
||||
private final DevOpsUserMapper devOpsUserMapper;
|
||||
public final static String SUPER_USERNAME = "admin";
|
||||
|
||||
@Value("${devops.password:kafka-console-ui521}")
|
||||
private String password;
|
||||
|
||||
@Override
|
||||
public void afterSingletonsInstantiated() {
|
||||
QueryWrapper<DevOpsUserDO> userDOQueryWrapper = new QueryWrapper<>();
|
||||
userDOQueryWrapper.eq("username", SUPER_USERNAME);
|
||||
DevOpsUserDO userDO = devOpsUserMapper.selectOne(userDOQueryWrapper);
|
||||
if (userDO == null){
|
||||
DevOpsUserDO devOpsUserDO = new DevOpsUserDO();
|
||||
devOpsUserDO.setUsername(SUPER_USERNAME);
|
||||
devOpsUserDO.setPassword(Md5Utils.MD5(password));
|
||||
devOpsUserDO.setRole(Role.manager);
|
||||
devOpsUserMapper.insert(devOpsUserDO);
|
||||
} else {
|
||||
userDO.setPassword(Md5Utils.MD5(password));
|
||||
devOpsUserMapper.updateById(userDO);
|
||||
}
|
||||
log.info("init super devops user done, username = {}", SUPER_USERNAME);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.xuxd.kafka.console.controller;
|
||||
|
||||
import com.xuxd.kafka.console.beans.AclUser;
|
||||
import com.xuxd.kafka.console.beans.annotation.RequiredAuthorize;
|
||||
import com.xuxd.kafka.console.service.AclService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
@@ -30,17 +31,20 @@ public class AclUserController {
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@RequiredAuthorize
|
||||
public Object addOrUpdateUser(@RequestBody AclUser user) {
|
||||
return aclService.addOrUpdateUser(user.getUsername(), user.getPassword());
|
||||
}
|
||||
|
||||
@DeleteMapping
|
||||
@RequiredAuthorize
|
||||
public Object deleteUser(@RequestBody AclUser user) {
|
||||
return aclService.deleteUser(user.getUsername());
|
||||
}
|
||||
|
||||
|
||||
@DeleteMapping("/auth")
|
||||
@RequiredAuthorize
|
||||
public Object deleteUserAndAuth(@RequestBody AclUser user) {
|
||||
return aclService.deleteUserAndAuth(user.getUsername());
|
||||
}
|
||||
|
||||
@@ -3,13 +3,7 @@ package com.xuxd.kafka.console.controller;
|
||||
import com.xuxd.kafka.console.beans.dto.ClusterInfoDTO;
|
||||
import com.xuxd.kafka.console.service.ClusterService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* kafka-console-ui.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.xuxd.kafka.console.controller;
|
||||
|
||||
import com.xuxd.kafka.console.beans.ResponseData;
|
||||
import com.xuxd.kafka.console.beans.annotation.RequiredAuthorize;
|
||||
import com.xuxd.kafka.console.beans.dto.AlterConfigDTO;
|
||||
import com.xuxd.kafka.console.beans.enums.AlterType;
|
||||
import com.xuxd.kafka.console.config.KafkaConfig;
|
||||
@@ -47,11 +48,13 @@ public class ConfigController {
|
||||
}
|
||||
|
||||
@PostMapping("/topic")
|
||||
@RequiredAuthorize
|
||||
public Object setTopicConfig(@RequestBody AlterConfigDTO dto) {
|
||||
return configService.alterTopicConfig(dto.getEntity(), dto.to(), AlterType.SET);
|
||||
}
|
||||
|
||||
@DeleteMapping("/topic")
|
||||
@RequiredAuthorize
|
||||
public Object deleteTopicConfig(@RequestBody AlterConfigDTO dto) {
|
||||
return configService.alterTopicConfig(dto.getEntity(), dto.to(), AlterType.DELETE);
|
||||
}
|
||||
@@ -62,11 +65,13 @@ public class ConfigController {
|
||||
}
|
||||
|
||||
@PostMapping("/broker")
|
||||
@RequiredAuthorize
|
||||
public Object setBrokerConfig(@RequestBody AlterConfigDTO dto) {
|
||||
return configService.alterBrokerConfig(dto.getEntity(), dto.to(), AlterType.SET);
|
||||
}
|
||||
|
||||
@DeleteMapping("/broker")
|
||||
@RequiredAuthorize
|
||||
public Object deleteBrokerConfig(@RequestBody AlterConfigDTO dto) {
|
||||
return configService.alterBrokerConfig(dto.getEntity(), dto.to(), AlterType.DELETE);
|
||||
}
|
||||
@@ -77,11 +82,13 @@ public class ConfigController {
|
||||
}
|
||||
|
||||
@PostMapping("/broker/logger")
|
||||
@RequiredAuthorize
|
||||
public Object setBrokerLoggerConfig(@RequestBody AlterConfigDTO dto) {
|
||||
return configService.alterBrokerLoggerConfig(dto.getEntity(), dto.to(), AlterType.SET);
|
||||
}
|
||||
|
||||
@DeleteMapping("/broker/logger")
|
||||
@RequiredAuthorize
|
||||
public Object deleteBrokerLoggerConfig(@RequestBody AlterConfigDTO dto) {
|
||||
return configService.alterBrokerLoggerConfig(dto.getEntity(), dto.to(), AlterType.DELETE);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.xuxd.kafka.console.controller;
|
||||
|
||||
import com.xuxd.kafka.console.beans.ResponseData;
|
||||
import com.xuxd.kafka.console.beans.annotation.RequiredAuthorize;
|
||||
import com.xuxd.kafka.console.beans.dto.AddSubscriptionDTO;
|
||||
import com.xuxd.kafka.console.beans.dto.QueryConsumerGroupDTO;
|
||||
import com.xuxd.kafka.console.beans.dto.ResetOffsetDTO;
|
||||
@@ -67,11 +68,13 @@ public class ConsumerController {
|
||||
}
|
||||
|
||||
@PostMapping("/subscription")
|
||||
@RequiredAuthorize
|
||||
public Object addSubscription(@RequestBody AddSubscriptionDTO subscriptionDTO) {
|
||||
return consumerService.addSubscription(subscriptionDTO.getGroupId(), subscriptionDTO.getTopic());
|
||||
}
|
||||
|
||||
@PostMapping("/reset/offset")
|
||||
@RequiredAuthorize
|
||||
public Object restOffset(@RequestBody ResetOffsetDTO offsetDTO) {
|
||||
ResponseData res = ResponseData.create().failed("unknown");
|
||||
switch (offsetDTO.getLevel()) {
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.xuxd.kafka.console.controller;
|
||||
|
||||
import com.xuxd.kafka.console.beans.ResponseData;
|
||||
import com.xuxd.kafka.console.beans.annotation.RequiredAuthorize;
|
||||
import com.xuxd.kafka.console.beans.dto.user.*;
|
||||
import com.xuxd.kafka.console.beans.vo.DevOpsUserVO;
|
||||
import com.xuxd.kafka.console.beans.vo.LoginVO;
|
||||
import com.xuxd.kafka.console.service.DevOpsUserService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户管理
|
||||
* @author dongyinuo
|
||||
*/
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/devops/user")
|
||||
public class DevOpsUserController {
|
||||
|
||||
private final DevOpsUserService devOpsUserService;
|
||||
|
||||
@PostMapping("add")
|
||||
@RequiredAuthorize
|
||||
public ResponseData<Boolean> add(@RequestBody AddUserDTO addUserDTO){
|
||||
return devOpsUserService.add(addUserDTO);
|
||||
}
|
||||
|
||||
@PostMapping("update")
|
||||
@RequiredAuthorize
|
||||
public ResponseData<Boolean> update(@RequestBody UpdateUserDTO updateUserDTO){
|
||||
return devOpsUserService.update(updateUserDTO);
|
||||
}
|
||||
|
||||
@DeleteMapping
|
||||
@RequiredAuthorize
|
||||
public ResponseData<Boolean> delete(@RequestParam Long id){
|
||||
return devOpsUserService.delete(id);
|
||||
}
|
||||
|
||||
@GetMapping("list")
|
||||
@RequiredAuthorize
|
||||
public ResponseData<List<DevOpsUserVO>> list(@ModelAttribute ListUserDTO listUserDTO){
|
||||
return devOpsUserService.list(listUserDTO);
|
||||
}
|
||||
|
||||
@PostMapping("login")
|
||||
public ResponseData<LoginVO> login(@RequestBody LoginDTO loginDTO){
|
||||
return devOpsUserService.login(loginDTO.getUsername(), loginDTO.getPassword());
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.xuxd.kafka.console.controller;
|
||||
|
||||
import com.xuxd.kafka.console.beans.TopicPartition;
|
||||
import com.xuxd.kafka.console.beans.annotation.RequiredAuthorize;
|
||||
import com.xuxd.kafka.console.beans.dto.BrokerThrottleDTO;
|
||||
import com.xuxd.kafka.console.beans.dto.ProposedAssignmentDTO;
|
||||
import com.xuxd.kafka.console.beans.dto.ReplicationDTO;
|
||||
@@ -30,12 +31,14 @@ public class OperationController {
|
||||
private OperationService operationService;
|
||||
|
||||
@PostMapping("/sync/consumer/offset")
|
||||
@RequiredAuthorize
|
||||
public Object syncConsumerOffset(@RequestBody SyncDataDTO dto) {
|
||||
dto.getProperties().put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, dto.getAddress());
|
||||
return operationService.syncConsumerOffset(dto.getGroupId(), dto.getTopic(), dto.getProperties());
|
||||
}
|
||||
|
||||
@PostMapping("/sync/min/offset/alignment")
|
||||
@RequiredAuthorize
|
||||
public Object minOffsetAlignment(@RequestBody SyncDataDTO dto) {
|
||||
dto.getProperties().put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, dto.getAddress());
|
||||
return operationService.minOffsetAlignment(dto.getGroupId(), dto.getTopic(), dto.getProperties());
|
||||
@@ -47,6 +50,7 @@ public class OperationController {
|
||||
}
|
||||
|
||||
@DeleteMapping("/sync/alignment")
|
||||
@RequiredAuthorize
|
||||
public Object deleteAlignment(@RequestParam Long id) {
|
||||
return operationService.deleteAlignmentById(id);
|
||||
}
|
||||
@@ -57,6 +61,7 @@ public class OperationController {
|
||||
}
|
||||
|
||||
@PostMapping("/broker/throttle")
|
||||
@RequiredAuthorize
|
||||
public Object configThrottle(@RequestBody BrokerThrottleDTO dto) {
|
||||
return operationService.configThrottle(dto.getBrokerList(), dto.getUnit().toKb(dto.getThrottle()));
|
||||
}
|
||||
@@ -77,6 +82,7 @@ public class OperationController {
|
||||
}
|
||||
|
||||
@PostMapping("/replication/reassignments/proposed")
|
||||
@RequiredAuthorize
|
||||
public Object proposedAssignments(@RequestBody ProposedAssignmentDTO dto) {
|
||||
return operationService.proposedAssignments(dto.getTopic(), dto.getBrokers());
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.xuxd.kafka.console.controller;
|
||||
|
||||
import com.xuxd.kafka.console.beans.ReplicaAssignment;
|
||||
import com.xuxd.kafka.console.beans.annotation.RequiredAuthorize;
|
||||
import com.xuxd.kafka.console.beans.dto.AddPartitionDTO;
|
||||
import com.xuxd.kafka.console.beans.dto.NewTopicDTO;
|
||||
import com.xuxd.kafka.console.beans.dto.TopicThrottleDTO;
|
||||
@@ -43,6 +44,7 @@ public class TopicController {
|
||||
}
|
||||
|
||||
@DeleteMapping
|
||||
@RequiredAuthorize
|
||||
public Object deleteTopic(@RequestParam String topic) {
|
||||
return topicService.deleteTopic(topic);
|
||||
}
|
||||
@@ -53,11 +55,13 @@ public class TopicController {
|
||||
}
|
||||
|
||||
@PostMapping("/new")
|
||||
@RequiredAuthorize
|
||||
public Object createNewTopic(@RequestBody NewTopicDTO topicDTO) {
|
||||
return topicService.createTopic(topicDTO.toNewTopic());
|
||||
}
|
||||
|
||||
@PostMapping("/partition/new")
|
||||
@RequiredAuthorize
|
||||
public Object addPartition(@RequestBody AddPartitionDTO partitionDTO) {
|
||||
String topic = partitionDTO.getTopic().trim();
|
||||
int addNum = partitionDTO.getAddNum();
|
||||
@@ -80,11 +84,13 @@ public class TopicController {
|
||||
}
|
||||
|
||||
@PostMapping("/replica/assignment")
|
||||
@RequiredAuthorize
|
||||
public Object updateReplicaAssignment(@RequestBody ReplicaAssignment assignment) {
|
||||
return topicService.updateReplicaAssignment(assignment);
|
||||
}
|
||||
|
||||
@PostMapping("/replica/throttle")
|
||||
@RequiredAuthorize
|
||||
public Object configThrottle(@RequestBody TopicThrottleDTO dto) {
|
||||
return topicService.configThrottle(dto.getTopic(), dto.getPartitions(), dto.getOperation());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.xuxd.kafka.console.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.xuxd.kafka.console.beans.dos.DevOpsUserDO;
|
||||
|
||||
public interface DevOpsUserMapper extends BaseMapper<DevOpsUserDO> {
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.xuxd.kafka.console.interceptor;
|
||||
|
||||
import com.xuxd.kafka.console.beans.ResponseData;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import com.xuxd.kafka.console.utils.ResponseUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
@@ -14,14 +13,13 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||
* @date 2021-10-19 14:32:18
|
||||
**/
|
||||
@Slf4j
|
||||
@ControllerAdvice(basePackages = "com.xuxd.kafka.console.controller")
|
||||
@ControllerAdvice(basePackages = "com.xuxd.kafka.console")
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
@ExceptionHandler(value = Exception.class)
|
||||
@ResponseBody
|
||||
public Object exceptionHandler(HttpServletRequest req, Exception ex) throws Exception {
|
||||
|
||||
public Object exceptionHandler(Exception ex) {
|
||||
log.error("exception handle: ", ex);
|
||||
return ResponseData.create().failed(ex.getMessage());
|
||||
return ResponseUtil.error(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.xuxd.kafka.console.interceptor;
|
||||
|
||||
import com.xuxd.kafka.console.beans.ResponseData;
|
||||
import com.xuxd.kafka.console.beans.annotation.RequiredAuthorize;
|
||||
import com.xuxd.kafka.console.beans.enums.Role;
|
||||
import com.xuxd.kafka.console.beans.vo.DevOpsUserVO;
|
||||
import com.xuxd.kafka.console.service.DevOpsUserService;
|
||||
import com.xuxd.kafka.console.utils.ContextUtil;
|
||||
import com.xuxd.kafka.console.utils.ConvertUtil;
|
||||
import com.xuxd.kafka.console.utils.JwtUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.AsyncHandlerInterceptor;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import static com.xuxd.kafka.console.beans.ResponseData.TOKEN_ILLEGAL;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class TokenInterceptor implements AsyncHandlerInterceptor {
|
||||
|
||||
private final static String TOKEN = "token";
|
||||
private final DevOpsUserService devOpsUserService;
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
if (handler instanceof HandlerMethod){
|
||||
String token = request.getHeader(TOKEN);
|
||||
if (StringUtils.isBlank(token)){
|
||||
log.info("token not exist");
|
||||
write(response);
|
||||
return false;
|
||||
}
|
||||
|
||||
String username = JwtUtils.parse(token);
|
||||
if (StringUtils.isBlank(username)){
|
||||
log.info("{} is wrongful", token);
|
||||
write(response);
|
||||
return false;
|
||||
}
|
||||
|
||||
ResponseData<DevOpsUserVO> userVORsp = devOpsUserService.detail(username);
|
||||
if (userVORsp == null || userVORsp.getData() == null){
|
||||
log.info("{} not exist", username);
|
||||
write(response);
|
||||
return false;
|
||||
}
|
||||
|
||||
ContextUtil.set(ContextUtil.USERNAME, username);
|
||||
HandlerMethod method = (HandlerMethod)handler;
|
||||
RequiredAuthorize annotation = method.getMethodAnnotation(RequiredAuthorize.class);
|
||||
if (annotation != null){
|
||||
DevOpsUserVO userVO = userVORsp.getData();
|
||||
if (!userVO.getRole().equals(Role.manager)){
|
||||
log.info("{},{} no permission", username, request.getRequestURI());
|
||||
write(response);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void write(HttpServletResponse response){
|
||||
PrintWriter writer = null;
|
||||
try {
|
||||
writer = response.getWriter();
|
||||
writer.write(ConvertUtil.toJsonString(ResponseData.create().failed(TOKEN_ILLEGAL)));
|
||||
} catch (Exception ignored){
|
||||
} finally {
|
||||
if (writer != null){
|
||||
writer.flush();
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.xuxd.kafka.console.interceptor;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
@RequiredArgsConstructor
|
||||
public class WebMvcConfig implements WebMvcConfigurer {
|
||||
|
||||
private final TokenInterceptor tokenInterceptor;
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(tokenInterceptor)
|
||||
.addPathPatterns("/**")
|
||||
.excludePathPatterns("/devops/user/login");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.xuxd.kafka.console.service;
|
||||
|
||||
import com.xuxd.kafka.console.beans.ResponseData;
|
||||
import com.xuxd.kafka.console.beans.dto.user.AddUserDTO;
|
||||
import com.xuxd.kafka.console.beans.dto.user.ListUserDTO;
|
||||
import com.xuxd.kafka.console.beans.dto.user.UpdateUserDTO;
|
||||
import com.xuxd.kafka.console.beans.vo.DevOpsUserVO;
|
||||
import com.xuxd.kafka.console.beans.vo.LoginVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface DevOpsUserService {
|
||||
|
||||
ResponseData<Boolean> add(AddUserDTO addUserDTO);
|
||||
|
||||
ResponseData<Boolean> update(UpdateUserDTO updateUserDTO);
|
||||
|
||||
ResponseData<Boolean> delete(Long id);
|
||||
|
||||
ResponseData<List<DevOpsUserVO>> list(ListUserDTO listUserDTO);
|
||||
|
||||
ResponseData<DevOpsUserVO> detail(String username);
|
||||
|
||||
ResponseData<LoginVO> login(String username, String password);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.xuxd.kafka.console.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.xuxd.kafka.console.beans.KafkaConsoleException;
|
||||
import com.xuxd.kafka.console.beans.ResponseData;
|
||||
import com.xuxd.kafka.console.beans.dos.DevOpsUserDO;
|
||||
import com.xuxd.kafka.console.beans.dto.user.AddUserDTO;
|
||||
import com.xuxd.kafka.console.beans.dto.user.ListUserDTO;
|
||||
import com.xuxd.kafka.console.beans.dto.user.UpdateUserDTO;
|
||||
import com.xuxd.kafka.console.beans.vo.DevOpsUserVO;
|
||||
import com.xuxd.kafka.console.beans.vo.LoginVO;
|
||||
import com.xuxd.kafka.console.boot.InitSuperDevOpsUser;
|
||||
import com.xuxd.kafka.console.dao.DevOpsUserMapper;
|
||||
import com.xuxd.kafka.console.service.DevOpsUserService;
|
||||
import com.xuxd.kafka.console.utils.ConvertUtil;
|
||||
import com.xuxd.kafka.console.utils.JwtUtils;
|
||||
import com.xuxd.kafka.console.utils.Md5Utils;
|
||||
import com.xuxd.kafka.console.utils.ResponseUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class DevOpsServiceImpl implements DevOpsUserService {
|
||||
|
||||
private final DevOpsUserMapper devOpsUserMapper;
|
||||
|
||||
@Override
|
||||
public ResponseData<Boolean> add(AddUserDTO addUserDTO) {
|
||||
QueryWrapper<DevOpsUserDO> queryWrapper = new QueryWrapper<DevOpsUserDO>();
|
||||
queryWrapper.eq("username", addUserDTO.getUsername());
|
||||
if (devOpsUserMapper.selectOne(queryWrapper) != null){
|
||||
throw new KafkaConsoleException("账号已存在");
|
||||
}
|
||||
|
||||
addUserDTO.setPassword(Md5Utils.MD5(addUserDTO.getPassword()));
|
||||
int ret = devOpsUserMapper.insert(ConvertUtil.copy(addUserDTO, DevOpsUserDO.class));
|
||||
return ResponseUtil.success(ret > 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseData<Boolean> update(UpdateUserDTO updateUserDTO) {
|
||||
UpdateWrapper<DevOpsUserDO> updateWrapper = new UpdateWrapper<>();
|
||||
if (updateUserDTO.getRole() != null){
|
||||
updateWrapper.set("role", updateUserDTO.getRole());
|
||||
}
|
||||
if (StringUtils.isNotBlank(updateUserDTO.getPassword())){
|
||||
updateWrapper.set("password", Md5Utils.MD5(updateUserDTO.getPassword()));
|
||||
}
|
||||
updateWrapper.eq("username", updateUserDTO.getUsername());
|
||||
int ret = devOpsUserMapper.update(null, updateWrapper);
|
||||
return ResponseUtil.success(ret > 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseData<Boolean> delete(Long id) {
|
||||
int ret = devOpsUserMapper.deleteById(id);
|
||||
return ResponseUtil.success(ret > 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseData<List<DevOpsUserVO>> list(ListUserDTO listUserDTO) {
|
||||
QueryWrapper<DevOpsUserDO> queryWrapper = new QueryWrapper<DevOpsUserDO>();
|
||||
if (listUserDTO.getId() != null){
|
||||
queryWrapper.eq("id", listUserDTO.getId());
|
||||
}
|
||||
if (StringUtils.isNotBlank(listUserDTO.getUsername())){
|
||||
queryWrapper.eq("username", listUserDTO.getUsername());
|
||||
}
|
||||
queryWrapper.ne("username", InitSuperDevOpsUser.SUPER_USERNAME);
|
||||
List<DevOpsUserDO> userDOS = devOpsUserMapper.selectList(queryWrapper);
|
||||
return ResponseUtil.success(ConvertUtil.copyList(userDOS, DevOpsUserVO.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseData<DevOpsUserVO> detail(String username) {
|
||||
QueryWrapper<DevOpsUserDO> queryWrapper = new QueryWrapper<DevOpsUserDO>();
|
||||
queryWrapper.eq("username", username);
|
||||
DevOpsUserDO userDO = devOpsUserMapper.selectOne(queryWrapper);
|
||||
return ResponseUtil.success(ConvertUtil.copy(userDO, DevOpsUserVO.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseData<LoginVO> login(String username, String password) {
|
||||
QueryWrapper<DevOpsUserDO> queryWrapper = new QueryWrapper<DevOpsUserDO>();
|
||||
queryWrapper.eq("username", username);
|
||||
queryWrapper.eq("password", Md5Utils.MD5(password));
|
||||
DevOpsUserDO userDO = devOpsUserMapper.selectOne(queryWrapper);
|
||||
if (userDO == null){
|
||||
throw new KafkaConsoleException("用户名或密码错误");
|
||||
}
|
||||
LoginVO loginVO = LoginVO.builder().role(userDO.getRole()).token(JwtUtils.sign(username)).build();
|
||||
return ResponseUtil.success(loginVO);
|
||||
}
|
||||
}
|
||||
23
src/main/java/com/xuxd/kafka/console/utils/ContextUtil.java
Normal file
23
src/main/java/com/xuxd/kafka/console/utils/ContextUtil.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package com.xuxd.kafka.console.utils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ContextUtil {
|
||||
|
||||
public static final String USERNAME = "username" ;
|
||||
|
||||
private static ThreadLocal<Map<String, Object>> context = ThreadLocal.withInitial(() -> new HashMap<>());
|
||||
|
||||
public static void set(String key, Object value){
|
||||
context.get().put(key, value);
|
||||
}
|
||||
|
||||
public static String get(String key){
|
||||
return (String) context.get().get(key);
|
||||
}
|
||||
|
||||
public static void clear(){
|
||||
context.remove();
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,15 @@
|
||||
package com.xuxd.kafka.console.utils;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.cglib.beans.BeanCopier;
|
||||
import org.springframework.objenesis.ObjenesisStd;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* kafka-console-ui.
|
||||
@@ -22,6 +20,47 @@ import org.springframework.util.ClassUtils;
|
||||
@Slf4j
|
||||
public class ConvertUtil {
|
||||
|
||||
private static ThreadLocal<ObjenesisStd> objenesisStdThreadLocal = ThreadLocal.withInitial(ObjenesisStd::new);
|
||||
private static ConcurrentHashMap<Class<?>, ConcurrentHashMap<Class<?>, BeanCopier>> cache = new ConcurrentHashMap<>();
|
||||
|
||||
public static <T> T copy(Object source, Class<T> target) {
|
||||
return copy(source, objenesisStdThreadLocal.get().newInstance(target));
|
||||
}
|
||||
|
||||
public static <T> T copy(Object source, T target) {
|
||||
if (null == source) {
|
||||
return null;
|
||||
}
|
||||
BeanCopier beanCopier = getCacheBeanCopier(source.getClass(), target.getClass());
|
||||
beanCopier.copy(source, target, null);
|
||||
return target;
|
||||
}
|
||||
|
||||
public static <T> List<T> copyList(List<?> sources, Class<T> target) {
|
||||
if (sources.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
ArrayList<T> list = new ArrayList<>(sources.size());
|
||||
ObjenesisStd objenesisStd = objenesisStdThreadLocal.get();
|
||||
for (Object source : sources) {
|
||||
if (source == null) {
|
||||
break;
|
||||
}
|
||||
T newInstance = objenesisStd.newInstance(target);
|
||||
BeanCopier beanCopier = getCacheBeanCopier(source.getClass(), target);
|
||||
beanCopier.copy(source, newInstance, null);
|
||||
list.add(newInstance);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private static <S, T> BeanCopier getCacheBeanCopier(Class<S> source, Class<T> target) {
|
||||
ConcurrentHashMap<Class<?>, BeanCopier> copierConcurrentHashMap =
|
||||
cache.computeIfAbsent(source, aClass -> new ConcurrentHashMap<>(16));
|
||||
return copierConcurrentHashMap.computeIfAbsent(target, aClass -> BeanCopier.create(source, target, false));
|
||||
}
|
||||
|
||||
public static Map<String, Object> toMap(Object src) {
|
||||
Preconditions.checkNotNull(src);
|
||||
Map<String, Object> res = new HashMap<>();
|
||||
|
||||
43
src/main/java/com/xuxd/kafka/console/utils/JwtUtils.java
Normal file
43
src/main/java/com/xuxd/kafka/console/utils/JwtUtils.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package com.xuxd.kafka.console.utils;
|
||||
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class JwtUtils {
|
||||
|
||||
private static final String ISSUER = "kafka-console-ui";
|
||||
private static final long EXPIRE_TIME = 5 * 24 * 60 * 60 * 1000;
|
||||
private static final String PRIVATE_KEY = "~hello!kafka=console^ui";
|
||||
|
||||
public static String sign(String username){
|
||||
Map<String,Object> header = new HashMap<>();
|
||||
header.put("typ","JWT");
|
||||
header.put("alg","HS256");
|
||||
Map<String,Object> claims = new HashMap<>();
|
||||
claims.put("username", username);
|
||||
return Jwts.builder()
|
||||
.setIssuer(ISSUER)
|
||||
.setHeader(header)
|
||||
.setClaims(claims)
|
||||
.setIssuedAt(new Date())
|
||||
.setExpiration(new Date(System.currentTimeMillis() + EXPIRE_TIME))
|
||||
.signWith(SignatureAlgorithm.HS256, PRIVATE_KEY)
|
||||
.compact();
|
||||
}
|
||||
|
||||
public static String parse(String token){
|
||||
try{
|
||||
Claims claims = Jwts.parser()
|
||||
.setSigningKey(PRIVATE_KEY)
|
||||
.parseClaimsJws(token).getBody();
|
||||
return (String) claims.get("username");
|
||||
}catch (Exception e){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
12
src/main/java/com/xuxd/kafka/console/utils/Md5Utils.java
Normal file
12
src/main/java/com/xuxd/kafka/console/utils/Md5Utils.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package com.xuxd.kafka.console.utils;
|
||||
|
||||
import org.springframework.util.DigestUtils;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class Md5Utils {
|
||||
|
||||
public static String MD5(String s) {
|
||||
return DigestUtils.md5DigestAsHex(s.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
15
src/main/java/com/xuxd/kafka/console/utils/ResponseUtil.java
Normal file
15
src/main/java/com/xuxd/kafka/console/utils/ResponseUtil.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package com.xuxd.kafka.console.utils;
|
||||
|
||||
import com.xuxd.kafka.console.beans.ResponseData;
|
||||
|
||||
public class ResponseUtil {
|
||||
|
||||
public static <T> ResponseData<T> success(T data) {
|
||||
return ResponseData.create().data(data);
|
||||
}
|
||||
|
||||
public static ResponseData<String> error(String msg) {
|
||||
return ResponseData.create().failed(msg);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user