From fa630a1d8988517778b79d071012abb277c9dc8a Mon Sep 17 00:00:00 2001 From: nagocoler Date: Wed, 13 Dec 2023 17:15:03 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=AD=90=E8=B4=A6=E6=88=B7?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E8=AE=BE=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/config/SecurityConfiguration.java | 3 +- .../example/controller/UserController.java | 23 +++++++++++++ .../java/com/example/entity/dto/Account.java | 1 + .../entity/vo/request/CreateSubAccountVO.java | 20 +++++++++++ .../entity/vo/response/SubAccountVO.java | 12 +++++++ .../filter/JwtAuthenticationFilter.java | 2 ++ .../com/example/service/AccountService.java | 7 ++++ .../service/impl/AccountServiceImpl.java | 34 +++++++++++++++++++ .../main/java/com/example/utils/Const.java | 7 ++-- .../main/java/com/example/utils/JwtUtils.java | 9 +++++ .../src/views/main/Security.vue | 17 ++++++++-- 11 files changed, 130 insertions(+), 5 deletions(-) create mode 100644 itbaima-monitor-server/src/main/java/com/example/entity/vo/request/CreateSubAccountVO.java create mode 100644 itbaima-monitor-server/src/main/java/com/example/entity/vo/response/SubAccountVO.java 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 ec0afe5..9ede5fc 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 @@ -56,7 +56,8 @@ public class SecurityConfiguration { .requestMatchers("/api/auth/**", "/error").permitAll() .requestMatchers("/monitor/**").permitAll() .requestMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll() - .anyRequest().hasAnyRole(Const.ROLE_DEFAULT) + .requestMatchers("/api/user/sub/**").hasRole(Const.ROLE_ADMIN) + .anyRequest().hasAnyRole(Const.ROLE_ADMIN, Const.ROLE_NORMAL) ) .formLogin(conf -> conf .loginProcessingUrl("/api/auth/login") diff --git a/itbaima-monitor-server/src/main/java/com/example/controller/UserController.java b/itbaima-monitor-server/src/main/java/com/example/controller/UserController.java index b7c1fa3..08690ff 100644 --- a/itbaima-monitor-server/src/main/java/com/example/controller/UserController.java +++ b/itbaima-monitor-server/src/main/java/com/example/controller/UserController.java @@ -2,12 +2,16 @@ package com.example.controller; import com.example.entity.RestBean; import com.example.entity.vo.request.ChangePasswordVO; +import com.example.entity.vo.request.CreateSubAccountVO; +import com.example.entity.vo.response.SubAccountVO; import com.example.service.AccountService; import com.example.utils.Const; import jakarta.annotation.Resource; import jakarta.validation.Valid; import org.springframework.web.bind.annotation.*; +import java.util.List; + @RestController @RequestMapping("/api/user") public class UserController { @@ -22,4 +26,23 @@ public class UserController { RestBean.success() : RestBean.failure(401, "原密码输入错误!"); } + @PostMapping("/sub/create") + public RestBean createSubAccount(@RequestBody @Valid CreateSubAccountVO vo) { + service.createSubAccount(vo); + return RestBean.success(); + } + + @GetMapping("/sub/delete") + public RestBean deleteSubAccount(int uid, + @RequestAttribute(Const.ATTR_USER_ID) int userId) { + if(uid == userId) + return RestBean.failure(401, "非法参数"); + service.deleteSubAccount(uid); + return RestBean.success(); + } + + @GetMapping("/sub/list") + public RestBean> subAccountList() { + return RestBean.success(service.listSubAccount()); + } } diff --git a/itbaima-monitor-server/src/main/java/com/example/entity/dto/Account.java b/itbaima-monitor-server/src/main/java/com/example/entity/dto/Account.java index 3fbfa1f..818588a 100644 --- a/itbaima-monitor-server/src/main/java/com/example/entity/dto/Account.java +++ b/itbaima-monitor-server/src/main/java/com/example/entity/dto/Account.java @@ -23,4 +23,5 @@ public class Account implements BaseData { String email; String role; Date registerTime; + String clients; } diff --git a/itbaima-monitor-server/src/main/java/com/example/entity/vo/request/CreateSubAccountVO.java b/itbaima-monitor-server/src/main/java/com/example/entity/vo/request/CreateSubAccountVO.java new file mode 100644 index 0000000..b65ee29 --- /dev/null +++ b/itbaima-monitor-server/src/main/java/com/example/entity/vo/request/CreateSubAccountVO.java @@ -0,0 +1,20 @@ +package com.example.entity.vo.request; + +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.Size; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import java.util.List; + +@Data +public class CreateSubAccountVO { + @Length(min = 1, max = 10) + String username; + @Email + String email; + @Length(min = 6, max = 20) + String password; + @Size(min = 1) + List clients; +} diff --git a/itbaima-monitor-server/src/main/java/com/example/entity/vo/response/SubAccountVO.java b/itbaima-monitor-server/src/main/java/com/example/entity/vo/response/SubAccountVO.java new file mode 100644 index 0000000..da52321 --- /dev/null +++ b/itbaima-monitor-server/src/main/java/com/example/entity/vo/response/SubAccountVO.java @@ -0,0 +1,12 @@ +package com.example.entity.vo.response; + +import com.alibaba.fastjson2.JSONArray; +import lombok.Data; + +@Data +public class SubAccountVO { + int id; + String username; + String email; + JSONArray clientList; +} 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 c959072..3c1f9b6 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 @@ -19,6 +19,7 @@ import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import java.io.IOException; +import java.util.ArrayList; /** * 用于对请求头中Jwt令牌进行校验的工具,为当前请求添加用户验证信息 @@ -60,6 +61,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(authentication); request.setAttribute(Const.ATTR_USER_ID, utils.toId(jwt)); + request.setAttribute(Const.ATTR_USER_ROLE, new ArrayList<>(user.getAuthorities()).get(0).getAuthority()); } } filterChain.doFilter(request, response); diff --git a/itbaima-monitor-server/src/main/java/com/example/service/AccountService.java b/itbaima-monitor-server/src/main/java/com/example/service/AccountService.java index eeb6299..95d29d4 100644 --- a/itbaima-monitor-server/src/main/java/com/example/service/AccountService.java +++ b/itbaima-monitor-server/src/main/java/com/example/service/AccountService.java @@ -3,13 +3,20 @@ package com.example.service; import com.baomidou.mybatisplus.extension.service.IService; import com.example.entity.dto.Account; import com.example.entity.vo.request.ConfirmResetVO; +import com.example.entity.vo.request.CreateSubAccountVO; import com.example.entity.vo.request.EmailResetVO; +import com.example.entity.vo.response.SubAccountVO; import org.springframework.security.core.userdetails.UserDetailsService; +import java.util.List; + public interface AccountService extends IService, UserDetailsService { Account findAccountByNameOrEmail(String text); String registerEmailVerifyCode(String type, String email, String address); String resetEmailAccountPassword(EmailResetVO info); String resetConfirm(ConfirmResetVO info); boolean changePassword(int id, String oldPass, String newPass); + void createSubAccount(CreateSubAccountVO vo); + void deleteSubAccount(int uid); + List listSubAccount(); } diff --git a/itbaima-monitor-server/src/main/java/com/example/service/impl/AccountServiceImpl.java b/itbaima-monitor-server/src/main/java/com/example/service/impl/AccountServiceImpl.java index f347d27..1ea1a7b 100644 --- a/itbaima-monitor-server/src/main/java/com/example/service/impl/AccountServiceImpl.java +++ b/itbaima-monitor-server/src/main/java/com/example/service/impl/AccountServiceImpl.java @@ -1,10 +1,13 @@ package com.example.service.impl; +import com.alibaba.fastjson2.JSONArray; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.example.entity.dto.Account; import com.example.entity.vo.request.ConfirmResetVO; +import com.example.entity.vo.request.CreateSubAccountVO; import com.example.entity.vo.request.EmailResetVO; +import com.example.entity.vo.response.SubAccountVO; import com.example.mapper.AccountMapper; import com.example.service.AccountService; import com.example.utils.Const; @@ -19,6 +22,8 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; +import java.util.Date; +import java.util.List; import java.util.Map; import java.util.Random; import java.util.concurrent.TimeUnit; @@ -127,6 +132,35 @@ public class AccountServiceImpl extends ServiceImpl impl return true; } + @Override + public void createSubAccount(CreateSubAccountVO vo) { + Account account = this.findAccountByNameOrEmail(vo.getEmail()); + if(account != null) + throw new IllegalArgumentException("该电子邮件已被注册"); + account = this.findAccountByNameOrEmail(vo.getUsername()); + if(account != null) + throw new IllegalArgumentException("该用户名已被注册"); + account = new Account(null, vo.getUsername(), passwordEncoder.encode(vo.getPassword()), + vo.getEmail(), Const.ROLE_NORMAL, new Date(), JSONArray.copyOf(vo.getClients()).toJSONString()); + this.save(account); + } + + @Override + public void deleteSubAccount(int uid) { + this.removeById(uid); + + } + + @Override + public List listSubAccount() { + return this.list(Wrappers.query().eq("role", Const.ROLE_NORMAL)) + .stream().map(account -> { + SubAccountVO vo = account.asViewObject(SubAccountVO.class); + vo.setClientList(JSONArray.parse(account.getClients())); + return vo; + }).toList(); + } + /** * 移除Redis中存储的邮件验证码 * @param email 电邮 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 fef2020..81f29ab 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 @@ -7,6 +7,8 @@ public final class Const { //JWT令牌 public final static String JWT_BLACK_LIST = "jwt:blacklist:"; public final static String JWT_FREQUENCY = "jwt:frequency:"; + //用户 + public final static String USER_BLACK_LIST = "user:blacklist:"; //请求频率限制 public final static String FLOW_LIMIT_COUNTER = "flow:counter:"; public final static String FLOW_LIMIT_BLOCK = "flow:block:"; @@ -18,10 +20,11 @@ public final class Const { public final static int ORDER_CORS = -102; //请求自定义属性 public final static String ATTR_USER_ID = "userId"; + public final static String ATTR_USER_ROLE = "userRole"; public final static String ATTR_CLIENT = "client"; //消息队列 public final static String MQ_MAIL = "mail"; //用户角色 - public final static String ROLE_DEFAULT = "admin"; - + public final static String ROLE_ADMIN = "admin"; + public final static String ROLE_NORMAL = "user"; } diff --git a/itbaima-monitor-server/src/main/java/com/example/utils/JwtUtils.java b/itbaima-monitor-server/src/main/java/com/example/utils/JwtUtils.java index 269f7a8..163e1e4 100644 --- a/itbaima-monitor-server/src/main/java/com/example/utils/JwtUtils.java +++ b/itbaima-monitor-server/src/main/java/com/example/utils/JwtUtils.java @@ -109,6 +109,7 @@ public class JwtUtils { try { DecodedJWT verify = jwtVerifier.verify(token); if(this.isInvalidToken(verify.getId())) return null; + if(this.isInvalidUser(verify.getClaim("id").asInt())) return null; Map claims = verify.getClaims(); return new Date().after(claims.get("exp").asDate()) ? null : verify; } catch (JWTVerificationException e) { @@ -177,6 +178,14 @@ public class JwtUtils { return true; } + public void deleteUser(int uid) { + template.opsForValue().set(Const.USER_BLACK_LIST + uid, "", expire, TimeUnit.HOURS); + } + + private boolean isInvalidUser(int uid){ + return Boolean.TRUE.equals(template.hasKey(Const.USER_BLACK_LIST + uid)); + } + /** * 验证Token是否被列入Redis黑名单 * @param uuid 令牌ID diff --git a/itbaima-monitor-web/src/views/main/Security.vue b/itbaima-monitor-web/src/views/main/Security.vue index 00eec5f..9eb41df 100644 --- a/itbaima-monitor-web/src/views/main/Security.vue +++ b/itbaima-monitor-web/src/views/main/Security.vue @@ -1,6 +1,6 @@