feat: 根据token分页查询用户日志和用户信息
This commit is contained in:
parent
fd63363101
commit
e2fb65cc29
91
ReadMe.md
91
ReadMe.md
|
@ -1,4 +1,62 @@
|
|||
# 搭建后端运行环境
|
||||
# 接口说明
|
||||
|
||||
## 请求接口
|
||||
|
||||
请求接口都是`/admin`前缀,部分接口会被忽略,忽略接口看下面。
|
||||
|
||||
所有分页请求内容都是通过路径传参方式
|
||||
|
||||
请求时需要带有token,只要前端在请求头中添加`token:内容`即可
|
||||
|
||||
采用SpringSecurity验证
|
||||
|
||||
## 接口忽略
|
||||
|
||||
### SpringSecurity接口忽略
|
||||
|
||||
这是相关拦截请求内容,如果要访问接口必须携带token,但是有些接口是不需要token的,不需要token就配置在这里。但是放在这里后,如果用户请求的地址是被忽略的,那么也就拿不到token也就拿不到登录相关信息。
|
||||
|
||||
获取用户自身的登录请求是不需要携带用户Id,只要有token去解析即可。
|
||||
|
||||
```java
|
||||
// 排出鉴定路径
|
||||
@Bean
|
||||
public WebSecurityCustomizer webSecurityCustomizer() {
|
||||
String[] annotations = {
|
||||
"/", "/ws/**",
|
||||
"/*/*/noAuth/**", "/*/noAuth/**", "/noAuth/**",
|
||||
"/media.ico", "/favicon.ico", "*.html", "/webjars/**", "/v3/api-docs/**", "swagger-ui/**",
|
||||
"/*/files/**",
|
||||
"/error", "/*/i18n/getI18n",
|
||||
};
|
||||
return web -> web.ignoring().requestMatchers(annotations)
|
||||
.requestMatchers(RegexRequestMatcher.regexMatcher(".*\\.(css|js)$"));
|
||||
}
|
||||
```
|
||||
|
||||

|
||||
|
||||
有些会被忽略的接口,凡是带有`noAuth`都是不需要验证的,但是要注意一点,不需要验证但是后端需要拿到登录相关信息是拿不到的。
|
||||
|
||||

|
||||
|
||||
我是将用户相关请求使用SpringSecurity进行拦截,如果有相关匹配路径那么就会被拦截,此时接口参数中会带有token内容,拿到token进行解析,之后取出相关用户信息,比如用户Id、username等。
|
||||
|
||||
将这些信息拿出来后放到ThreadLocal中,存储在线程中,如果微服务中需要需要放在请求头中,因为微服务不在同一个线程中。这个操作适合单体或者是微服务中不需要请求其它微服务的方式。
|
||||
|
||||

|
||||
|
||||
### 不需要管理接口
|
||||
|
||||
请求是会有不需要登录就能访问的接口,也需要不要被管理的接口
|
||||
|
||||
## 验证码验证忽略
|
||||
|
||||
为了公网上的展示,如果需要获取验证码比较的麻烦,如果你的需求和我一样那么可以在这里放开这些注释
|
||||
|
||||

|
||||
|
||||
# 搭建后端环境
|
||||
|
||||
1. 需要JDK17
|
||||
2. MySQL
|
||||
|
@ -42,6 +100,7 @@ docker rm slave_3304
|
|||
docker run --name slave_3304 -p 3304:3306 \
|
||||
-v /bunny/docker_data/mysql/slave_3304/etc/my.cnf:/etc/my.cnf \
|
||||
-v /bunny/docker_data/mysql/slave_3304/data:/var/lib/mysql \
|
||||
-v /bunny/docker_data/mysql/slave_3304/backup:\
|
||||
--restart=always --privileged=true \
|
||||
-e MYSQL_ROOT_PASSWORD=02120212 \
|
||||
-e TZ=Asia/Shanghai \
|
||||
|
@ -62,11 +121,10 @@ FLUSH PRIVILEGES;
|
|||
|
||||
```shell
|
||||
[mysqld]
|
||||
datadir=/var/lib/mysql
|
||||
socket=/var/lib/mysql/mysql.sock
|
||||
skip-host-cache
|
||||
skip-name-resolve
|
||||
secure-file-priv=/var/lib/mysql-files
|
||||
user=mysql
|
||||
|
||||
# 设置字符集
|
||||
character-set-server=utf8mb4
|
||||
|
@ -80,9 +138,6 @@ log-bin=mysql-bin
|
|||
|
||||
# 设置表名不区分大小写
|
||||
lower_case_table_names = 1
|
||||
|
||||
[client]
|
||||
socket=/var/run/mysqld/mysqld.sock
|
||||
```
|
||||
|
||||
## 安装Redis
|
||||
|
@ -119,6 +174,30 @@ docker run -d \
|
|||
minio/minio server /data --console-address ":9090"
|
||||
```
|
||||
|
||||
# 动态定时任务
|
||||
|
||||
使用`Quartz `数据存储在数据库中持久化存储.
|
||||
|
||||
所有的Quartz内容都放在这个目录中,因为前端需要知道有哪些定时任务,这时候又不能将数据添加到数据库中,如果以后需要更多的定时任务那么需要再数据库中添加,这样做很麻烦。
|
||||
|
||||
我们可以通过反射只要约定好内容,通过反射扫描的方式来获取这些可以使用的定时任务,反射的注解是这个:`@QuartzSchedulers(type = "test", description = "JobHello任务内容")`
|
||||
|
||||

|
||||
|
||||
## 注解说明
|
||||
|
||||
扫描注解包,可以通过依赖注入的方式使用
|
||||
|
||||

|
||||
|
||||
类型注解存放位置在下面。
|
||||
|
||||

|
||||
|
||||
获取所有可用定时任务
|
||||
|
||||

|
||||
|
||||
# Quartz 方法
|
||||
|
||||
## TriggerBuilder
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 173 KiB |
Binary file not shown.
After Width: | Height: | Size: 118 KiB |
Binary file not shown.
After Width: | Height: | Size: 239 KiB |
Binary file not shown.
After Width: | Height: | Size: 218 KiB |
|
@ -19,12 +19,18 @@ public class AnnotationScanner {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Set<Class<?>> getClassesWithAnnotation(Class<?> annotation) {
|
||||
// 设置是否延迟初始化
|
||||
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
|
||||
// 只需要带有 Annotation 注解类的内容
|
||||
scanner.addIncludeFilter(new AnnotationTypeFilter((Class<? extends Annotation>) annotation));
|
||||
|
||||
// 扫描到的内容,排除重复的内容
|
||||
Set<Class<?>> classes = new HashSet<>();
|
||||
|
||||
// 只要 cn.bunny.services 包下面的全部内容
|
||||
for (BeanDefinition bd : scanner.findCandidateComponents("cn.bunny.services")) {
|
||||
try {
|
||||
// 通过反射加载类,并将类名转换为 Class 对象
|
||||
Class<?> clazz = Class.forName(bd.getBeanClassName());
|
||||
classes.add(clazz);
|
||||
} catch (ClassNotFoundException e) {
|
||||
|
|
|
@ -52,7 +52,7 @@ public class EmailUsersController {
|
|||
}
|
||||
|
||||
@Operation(summary = "获取所有邮箱配置用户", description = "获取所有邮箱配置用户")
|
||||
@GetMapping("getAllMailboxConfigurationUsers")
|
||||
@GetMapping("noManage/getAllMailboxConfigurationUsers")
|
||||
public Mono<Result<List<Map<String, String>>>> getAllMailboxConfigurationUsers() {
|
||||
List<Map<String, String>> list = emailUsersService.getAllMailboxConfigurationUsers();
|
||||
return Mono.just(Result.success(list));
|
||||
|
|
|
@ -62,14 +62,14 @@ public class FilesController {
|
|||
}
|
||||
|
||||
@Operation(summary = "获取所有文件类型", description = "获取所有文件类型")
|
||||
@GetMapping("getAllMediaTypes")
|
||||
@GetMapping("noManage/getAllMediaTypes")
|
||||
public Mono<Result<Set<String>>> getAllMediaTypes() {
|
||||
Set<String> list = filesService.getAllMediaTypes();
|
||||
return Mono.just(Result.success(list));
|
||||
}
|
||||
|
||||
@Operation(summary = "获取所有文件存储基础路径", description = "获取所有文件存储基础路径")
|
||||
@GetMapping("getAllFilesStoragePath")
|
||||
@GetMapping("noManage/getAllFilesStoragePath")
|
||||
public Mono<Result<List<String>>> getAllFilesStoragePath() {
|
||||
Map<String, String> typeMap = MinioConstant.typeMap;
|
||||
List<String> list = typeMap.keySet().stream().toList();
|
||||
|
|
|
@ -50,7 +50,7 @@ public class MenuIconController {
|
|||
}
|
||||
|
||||
@Operation(summary = "获取查询图标名称列", description = "获取查询图标名称列")
|
||||
@GetMapping("getIconNameList")
|
||||
@GetMapping("noManage/getIconNameList")
|
||||
public Mono<Result<List<MenuIconVo>>> getIconNameList(String iconName) {
|
||||
List<MenuIconVo> voList = menuIconService.getIconNameList(iconName);
|
||||
return Mono.just(Result.success(voList));
|
||||
|
|
|
@ -50,7 +50,7 @@ public class RoleController {
|
|||
}
|
||||
|
||||
@Operation(summary = "获取所有角色", description = "获取所有角色")
|
||||
@GetMapping("getAllRoles")
|
||||
@GetMapping("noManage/getAllRoles")
|
||||
public Mono<Result<List<RoleVo>>> getAllRoles() {
|
||||
List<RoleVo> roleVoList = roleService.getAllRoles();
|
||||
return Mono.just(Result.success(roleVoList));
|
||||
|
|
|
@ -29,7 +29,7 @@ public class RolePowerController {
|
|||
private RolePowerService rolePowerService;
|
||||
|
||||
@Operation(summary = "根据角色id获取权限内容", description = "角色列获取已选择的权限")
|
||||
@GetMapping("getPowerListByRoleId")
|
||||
@GetMapping("noManage/getPowerListByRoleId")
|
||||
public Mono<Result<List<String>>> getPowerListByRoleId(Long id) {
|
||||
List<String> voList = rolePowerService.getPowerListByRoleId(id);
|
||||
return Mono.just(Result.success(voList));
|
||||
|
|
|
@ -39,7 +39,7 @@ public class RouterController {
|
|||
private RouterService routerService;
|
||||
|
||||
@Operation(summary = "获取用户菜单", description = "获取用户菜单")
|
||||
@GetMapping("getRouterAsync")
|
||||
@GetMapping("noManage/getRouterAsync")
|
||||
public Mono<Result<List<UserRouterVo>>> getRouterAsync() {
|
||||
List<UserRouterVo> voList = routerService.getRouterAsync();
|
||||
return Mono.just(Result.success(voList));
|
||||
|
|
|
@ -51,7 +51,7 @@ public class SchedulersController {
|
|||
}
|
||||
|
||||
@Operation(summary = "获取所有可用调度任务", description = "获取所有可用调度任务")
|
||||
@GetMapping("getAllScheduleJobList")
|
||||
@GetMapping("noManage/getAllScheduleJobList")
|
||||
public Mono<Result<List<Map<String, String>>>> getAllScheduleJobList() {
|
||||
List<Map<String, String>> mapList = schedulersService.getAllScheduleJobList();
|
||||
return Mono.just(Result.success(mapList));
|
||||
|
|
|
@ -42,6 +42,13 @@ public class UserController {
|
|||
return Mono.just(Result.success(pageResult));
|
||||
}
|
||||
|
||||
@Operation(summary = "获取本地登录用户信息", description = "获取本地登录用户信息")
|
||||
@GetMapping("noManage/getUserinfo")
|
||||
public Mono<Result<UserVo>> getUserinfo() {
|
||||
UserVo vo = userService.getUserinfo();
|
||||
return Mono.just(Result.success(vo));
|
||||
}
|
||||
|
||||
@Operation(summary = "获取用户信息", description = "获取用户信息")
|
||||
@GetMapping("getUserinfoById")
|
||||
public Mono<Result<UserVo>> getUserinfoById(Long id) {
|
||||
|
@ -50,7 +57,7 @@ public class UserController {
|
|||
}
|
||||
|
||||
@Operation(summary = "多条件查询用户", description = "多条件查询用户")
|
||||
@GetMapping("queryUser")
|
||||
@GetMapping("noManage/queryUser")
|
||||
public Mono<Result<List<AdminUserVo>>> queryUser(String keyword) {
|
||||
List<AdminUserVo> voList = userService.queryUser(keyword);
|
||||
return Mono.just(Result.success(voList));
|
||||
|
@ -113,7 +120,7 @@ public class UserController {
|
|||
}
|
||||
|
||||
@Operation(summary = "退出登录", description = "退出登录")
|
||||
@PostMapping("logout")
|
||||
@PostMapping("noManage/logout")
|
||||
public Result<String> logout() {
|
||||
userService.logout();
|
||||
return Result.success(ResultCodeEnum.LOGOUT_SUCCESS);
|
||||
|
|
|
@ -46,6 +46,18 @@ public class UserLoginLogController {
|
|||
return Mono.just(Result.success(pageResult));
|
||||
}
|
||||
|
||||
@Operation(summary = "获取本地用户登录日志", description = "获取本地用户登录日志")
|
||||
@GetMapping("noManage/getUserLoginLogListByLocalUser/{page}/{limit}")
|
||||
public Mono<Result<PageResult<UserLoginLogVo>>> getUserLoginLogListByLocalUser(
|
||||
@Parameter(name = "page", description = "当前页", required = true)
|
||||
@PathVariable("page") Integer page,
|
||||
@Parameter(name = "limit", description = "每页记录数", required = true)
|
||||
@PathVariable("limit") Integer limit) {
|
||||
Page<UserLoginLog> pageParams = new Page<>(page, limit);
|
||||
PageResult<UserLoginLogVo> voPageResult = userLoginLogService.getUserLoginLogListByLocalUser(pageParams);
|
||||
return Mono.just(Result.success(voPageResult));
|
||||
}
|
||||
|
||||
@Operation(summary = "删除用户登录日志", description = "删除用户登录日志")
|
||||
@DeleteMapping("deleteUserLoginLog")
|
||||
public Mono<Result<String>> deleteUserLoginLog(@RequestBody List<Long> ids) {
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
package cn.bunny.services.factory;
|
||||
|
||||
import cn.bunny.dao.entity.log.UserLoginLog;
|
||||
import cn.bunny.dao.pojo.result.PageResult;
|
||||
import cn.bunny.dao.vo.log.UserLoginLogVo;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class UserLoginLogFactory {
|
||||
|
||||
/**
|
||||
* 用户登录日志分页查询通用方法
|
||||
*
|
||||
* @param page 分页结果
|
||||
* @return 分页用户登录日志
|
||||
*/
|
||||
public PageResult<UserLoginLogVo> getUserLoginLogVoPageResult(IPage<UserLoginLog> page) {
|
||||
List<UserLoginLogVo> voList = page.getRecords().stream().map(userLoginLog -> {
|
||||
UserLoginLogVo userLoginLogVo = new UserLoginLogVo();
|
||||
BeanUtils.copyProperties(userLoginLog, userLoginLogVo);
|
||||
return userLoginLogVo;
|
||||
}).toList();
|
||||
|
||||
return PageResult.<UserLoginLogVo>builder()
|
||||
.list(voList)
|
||||
.pageNo(page.getCurrent())
|
||||
.pageSize(page.getSize())
|
||||
.total(page.getTotal())
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -36,4 +36,12 @@ public interface UserLoginLogMapper extends BaseMapper<UserLoginLog> {
|
|||
* @param ids 删除 id 列表
|
||||
*/
|
||||
void deleteBatchIdsWithPhysics(List<Long> ids);
|
||||
|
||||
/**
|
||||
* * 分页查询根据用户Id用户登录日志内容
|
||||
*
|
||||
* @param pageParams 分页查询内容
|
||||
* @return 用户登录日志返回列表
|
||||
*/
|
||||
IPage<UserLoginLog> selectListByPageWithLocalUser(Page<UserLoginLog> pageParams, Long id);
|
||||
}
|
||||
|
|
|
@ -55,14 +55,17 @@ public class CustomAuthorizationManagerServiceImpl implements AuthorizationManag
|
|||
boolean checkedAdmin = CustomCheckIsAdmin.checkAdmin(roleCodeList, loginVo);
|
||||
if (checkedAdmin) return true;
|
||||
|
||||
// 不是 admin,查询角色权限关系表
|
||||
List<String> powerCodes = loginVo.getPermissions();
|
||||
// 判断请求地址是否是 noManage 不需要被验证的
|
||||
String requestURI = request.getRequestURI();
|
||||
if (requestURI.contains("noManage")) return true;
|
||||
|
||||
// 根据权限码查询可以访问URL
|
||||
// 不是 admin,查询角色权限关系表,根据权限码查询可以访问URL
|
||||
List<String> powerCodes = loginVo.getPermissions();
|
||||
List<Power> powerList = powerMapper.selectListByPowerCodes(powerCodes);
|
||||
|
||||
// 判断是否与请求路径匹配
|
||||
return powerList.stream().anyMatch(power -> AntPathRequestMatcher.antMatcher(power.getRequestUrl()).matches(request) ||
|
||||
request.getRequestURI().matches(power.getRequestUrl()));
|
||||
return powerList.stream()
|
||||
.anyMatch(power -> AntPathRequestMatcher.antMatcher(power.getRequestUrl()).matches(request) ||
|
||||
requestURI.matches(power.getRequestUrl()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,4 +32,12 @@ public interface UserLoginLogService extends IService<UserLoginLog> {
|
|||
* @param ids 删除id列表
|
||||
*/
|
||||
void deleteUserLoginLog(List<Long> ids);
|
||||
|
||||
/**
|
||||
* * 获取本地用户登录日志
|
||||
*
|
||||
* @param pageParams 分页查询内容
|
||||
* @return 用户登录日志返回列表
|
||||
*/
|
||||
PageResult<UserLoginLogVo> getUserLoginLogListByLocalUser(Page<UserLoginLog> pageParams);
|
||||
}
|
||||
|
|
|
@ -115,4 +115,11 @@ public interface UserService extends IService<AdminUser> {
|
|||
* @param dto 管理员用户修改密码
|
||||
*/
|
||||
void updateUserStatusByAdmin(AdminUserUpdateUserStatusDto dto);
|
||||
|
||||
/**
|
||||
* * 获取本地登录用户信息
|
||||
*
|
||||
* @return 用户信息
|
||||
*/
|
||||
UserVo getUserinfo();
|
||||
}
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
package cn.bunny.services.service.impl;
|
||||
|
||||
import cn.bunny.common.service.context.BaseContext;
|
||||
import cn.bunny.dao.dto.log.UserLoginLogDto;
|
||||
import cn.bunny.dao.entity.log.UserLoginLog;
|
||||
import cn.bunny.dao.pojo.result.PageResult;
|
||||
import cn.bunny.dao.vo.log.UserLoginLogVo;
|
||||
import cn.bunny.services.factory.UserLoginLogFactory;
|
||||
import cn.bunny.services.mapper.UserLoginLogMapper;
|
||||
import cn.bunny.services.service.UserLoginLogService;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -25,6 +27,9 @@ import java.util.List;
|
|||
@Service
|
||||
public class UserLoginLogServiceImpl extends ServiceImpl<UserLoginLogMapper, UserLoginLog> implements UserLoginLogService {
|
||||
|
||||
@Autowired
|
||||
private UserLoginLogFactory factory;
|
||||
|
||||
/**
|
||||
* * 用户登录日志 服务实现类
|
||||
*
|
||||
|
@ -37,18 +42,7 @@ public class UserLoginLogServiceImpl extends ServiceImpl<UserLoginLogMapper, Use
|
|||
// 分页查询菜单图标
|
||||
IPage<UserLoginLog> page = baseMapper.selectListByPage(pageParams, dto);
|
||||
|
||||
List<UserLoginLogVo> voList = page.getRecords().stream().map(userLoginLog -> {
|
||||
UserLoginLogVo userLoginLogVo = new UserLoginLogVo();
|
||||
BeanUtils.copyProperties(userLoginLog, userLoginLogVo);
|
||||
return userLoginLogVo;
|
||||
}).toList();
|
||||
|
||||
return PageResult.<UserLoginLogVo>builder()
|
||||
.list(voList)
|
||||
.pageNo(page.getCurrent())
|
||||
.pageSize(page.getSize())
|
||||
.total(page.getTotal())
|
||||
.build();
|
||||
return factory.getUserLoginLogVoPageResult(page);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -60,4 +54,18 @@ public class UserLoginLogServiceImpl extends ServiceImpl<UserLoginLogMapper, Use
|
|||
public void deleteUserLoginLog(List<Long> ids) {
|
||||
baseMapper.deleteBatchIdsWithPhysics(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* * 获取本地用户登录日志
|
||||
*
|
||||
* @param pageParams 分页查询内容
|
||||
* @return 用户登录日志返回列表
|
||||
*/
|
||||
@Override
|
||||
public PageResult<UserLoginLogVo> getUserLoginLogListByLocalUser(Page<UserLoginLog> pageParams) {
|
||||
Long userId = BaseContext.getUserId();
|
||||
IPage<UserLoginLog> page = baseMapper.selectListByPageWithLocalUser(pageParams, userId);
|
||||
|
||||
return factory.getUserLoginLogVoPageResult(page);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -301,6 +301,27 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implemen
|
|||
updateById(adminUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* * 获取本地登录用户信息
|
||||
*
|
||||
* @return 用户信息
|
||||
*/
|
||||
@Override
|
||||
public UserVo getUserinfo() {
|
||||
// 查询当前用户信息
|
||||
Long userId = BaseContext.getUserId();
|
||||
AdminUser adminUser = getOne(Wrappers.<AdminUser>lambdaQuery().eq(AdminUser::getId, userId));
|
||||
|
||||
// 赋值对象
|
||||
UserVo userVo = new UserVo();
|
||||
BeanUtils.copyProperties(adminUser, userVo);
|
||||
|
||||
// 设置用户头像内容
|
||||
String avatar = adminUser.getAvatar();
|
||||
if (StringUtils.hasText(avatar)) userVo.setAvatar(minioUtil.getObjectNameFullPath(avatar));
|
||||
return userVo;
|
||||
}
|
||||
|
||||
/**
|
||||
* * 用户信息 服务实现类
|
||||
*
|
||||
|
|
|
@ -70,6 +70,13 @@
|
|||
</where>
|
||||
</select>
|
||||
|
||||
<!-- 分页查询根据用户Id用户登录日志内容 -->
|
||||
<select id="selectListByPageWithLocalUser" resultType="cn.bunny.dao.entity.log.UserLoginLog">
|
||||
select
|
||||
<include refid="Base_Column_List"/>
|
||||
from log_user_login where user_id = #{id} order by create_time desc
|
||||
</select>
|
||||
|
||||
<!-- 物理删除用户登录日志 -->
|
||||
<delete id="deleteBatchIdsWithPhysics">
|
||||
delete
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"Version": "5.8.0",
|
||||
"Title": "BunnyAdmin",
|
||||
"Copyright": "Copyright © 2020-present",
|
||||
"FixedHeader": true,
|
||||
"HiddenSideBar": false,
|
||||
"MultiTagsCache": false,
|
||||
"KeepAlive": true,
|
||||
"Locale": "zh",
|
||||
"Layout": "vertical",
|
||||
"Theme": "light",
|
||||
"DarkMode": false,
|
||||
"OverallStyle": "light",
|
||||
"Grey": false,
|
||||
"Weak": false,
|
||||
"HideTabs": false,
|
||||
"HideFooter": false,
|
||||
"Stretch": false,
|
||||
"SidebarStatus": true,
|
||||
"EpThemeColor": "#409EFF",
|
||||
"ShowLogo": true,
|
||||
"ShowModel": "smart",
|
||||
"MenuArrowIconNoTransition": false,
|
||||
"CachingAsyncRoutes": false,
|
||||
"TooltipEffect": "light",
|
||||
"ResponsiveStorageNameSpace": "responsive-",
|
||||
"MenuSearchHistory": 6
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
<body style="margin: 0; padding: 0; background-color: #f5f5f5;">
|
||||
<div style="max-width: 600px; margin: 0 auto;">
|
||||
<table style="width: 100%; border-collapse: collapse; background-color: #ffffff; font-family: Arial, sans-serif;">
|
||||
<tr>
|
||||
<th style="height: 60px; padding: 20px; background-color: #0074d3; border-radius: 5px 5px 0 0;"
|
||||
valign="middle">
|
||||
<h1 style="margin: 0; color: #ffffff; font-size: 24px;">BunnyBBS邮箱验证码</h1>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 20px;">
|
||||
<div style="background-color: #ffffff; padding: 25px;">
|
||||
<h2 style="margin: 10px 0; font-size: 18px; color: #333333;">
|
||||
尊敬的用户,
|
||||
</h2>
|
||||
<p style="margin: 10px 0; font-size: 16px; color: #333333;">
|
||||
感谢您注册我们的产品. 您的账号正在进行电子邮件验证.
|
||||
</p>
|
||||
<p style="margin: 10px 0; font-size: 16px; color: #333333;">
|
||||
验证码为: <span class="button" style="color: #1100ff;">${verifyCode}</span>
|
||||
</p>
|
||||
<p style="margin: 10px 0; font-size: 16px; color: #333333;">
|
||||
验证码的有效期只有一分钟,请抓紧时间进行验证吧!
|
||||
</p>
|
||||
<p style="margin: 10px 0; font-size: 16px; color: #dc1818;">
|
||||
如果非本人操作,请忽略此邮件
|
||||
</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center; padding: 20px; background-color: #f5f5f5;">
|
||||
<p style="margin: 0; font-size: 12px; color: #747474;">
|
||||
XXXXX<br>
|
||||
Contact us: XXXXXXX@qq.com
|
||||
</p>
|
||||
<p style="margin: 10px 0; font-size: 12px; color: #747474;">
|
||||
This is an automated email, please do not reply.<br>
|
||||
© Company Name
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
|
@ -26,7 +26,9 @@ public class TestPath {
|
|||
// 执行后读取内容
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {System.out.println(line);}
|
||||
while ((line = reader.readLine()) != null) {
|
||||
System.out.println(line);
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package cn.bunny.services.security.service.impl;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class CustomAuthorizationManagerServiceImplTest {
|
||||
@Test
|
||||
void testRequestUrl() {
|
||||
String requestURI = "http://localhost:7000/api/user/noManage/getAdminUserList";
|
||||
System.out.println(requestURI.contains("noManage"));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue