mirror of
				https://gitee.com/lab1024/smart-admin.git
				synced 2025-11-04 18:33:43 +08:00 
			
		
		
		
	sa-token add login
This commit is contained in:
		@@ -125,6 +125,13 @@
 | 
			
		||||
                <version>${sa-token-version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <!-- Sa-Token 整合 jwt -->
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>cn.dev33</groupId>
 | 
			
		||||
                <artifactId>sa-token-jwt</artifactId>
 | 
			
		||||
                <version>1.35.0.RC</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <!-- sa-token end -->
 | 
			
		||||
 | 
			
		||||
            <dependency>
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,69 @@
 | 
			
		||||
package net.lab1024.sa.admin.interceptor;
 | 
			
		||||
 | 
			
		||||
import cn.dev33.satoken.stp.StpUtil;
 | 
			
		||||
import cn.hutool.core.convert.NumberWithFormat;
 | 
			
		||||
import net.lab1024.sa.common.common.domain.RequestUser;
 | 
			
		||||
import net.lab1024.sa.common.common.enumeration.UserTypeEnum;
 | 
			
		||||
import net.lab1024.sa.common.common.interceptor.AbstractInterceptor;
 | 
			
		||||
import net.lab1024.sa.common.common.util.SmartEnumUtil;
 | 
			
		||||
import net.lab1024.sa.common.handler.GlobalExceptionHandler;
 | 
			
		||||
import net.lab1024.sa.common.module.support.token.TokenService;
 | 
			
		||||
import org.springframework.context.annotation.Configuration;
 | 
			
		||||
 | 
			
		||||
import javax.servlet.http.HttpServletRequest;
 | 
			
		||||
import javax.servlet.http.HttpServletResponse;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * admin 拦截器
 | 
			
		||||
 *
 | 
			
		||||
 * @author: listen
 | 
			
		||||
 * @date: 2023/7/12 21:00
 | 
			
		||||
 */
 | 
			
		||||
@Configuration
 | 
			
		||||
public class AdminInterceptor extends AbstractInterceptor {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public RequestUser checkTokenAndGetUser() {
 | 
			
		||||
        /**
 | 
			
		||||
         * 检验当前会话是否已经登录, 如果未登录,则抛出异常:`NotLoginException`
 | 
			
		||||
         * 已在全局异常处理
 | 
			
		||||
         * @see GlobalExceptionHandler#handlerNotLoginException
 | 
			
		||||
         */
 | 
			
		||||
        StpUtil.checkLogin();
 | 
			
		||||
 | 
			
		||||
        // 获取额外数据
 | 
			
		||||
        Integer userType = ((NumberWithFormat) StpUtil.getExtra(TokenService.EXTRA_KEY_USER_TYPE)).intValue();
 | 
			
		||||
        UserTypeEnum userTypeEnum = SmartEnumUtil.getEnumByValue(userType, UserTypeEnum.class);
 | 
			
		||||
        String userName = (String) StpUtil.getExtra(TokenService.EXTRA_KEY_USER_NAME);
 | 
			
		||||
        String loginId = (String) StpUtil.getLoginId();
 | 
			
		||||
 | 
			
		||||
        // 当前请求对象
 | 
			
		||||
        RequestUser requestUser = new RequestUser();
 | 
			
		||||
        requestUser.setUserId(TokenService.getUserId(loginId));
 | 
			
		||||
        requestUser.setUserName(userName);
 | 
			
		||||
        requestUser.setUserType(userTypeEnum);
 | 
			
		||||
        return requestUser;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 配置拦截路径
 | 
			
		||||
     *
 | 
			
		||||
     * @return
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public String[] pathPatterns() {
 | 
			
		||||
        return new String[]{"/**"};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
 | 
			
		||||
        boolean isHandle = super.preHandle(request, response, handler);
 | 
			
		||||
        if (!isHandle) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // TODO listen 校验权限
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -8,7 +8,6 @@ import net.lab1024.sa.admin.module.business.oa.enterprise.domain.form.*;
 | 
			
		||||
import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseEmployeeVO;
 | 
			
		||||
import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseListVO;
 | 
			
		||||
import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseVO;
 | 
			
		||||
import net.lab1024.sa.common.common.annoation.SaAuth;
 | 
			
		||||
import net.lab1024.sa.common.common.domain.PageResult;
 | 
			
		||||
import net.lab1024.sa.common.common.domain.RequestUser;
 | 
			
		||||
import net.lab1024.sa.common.common.domain.ResponseDTO;
 | 
			
		||||
@@ -40,21 +39,18 @@ public class EnterpriseController {
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "分页查询企业模块 @author 开云")
 | 
			
		||||
    @PostMapping("/oa/enterprise/page/query")
 | 
			
		||||
    @SaAuth
 | 
			
		||||
    public ResponseDTO<PageResult<EnterpriseVO>> queryByPage(@RequestBody @Valid EnterpriseQueryForm queryDTO) {
 | 
			
		||||
        return enterpriseService.queryByPage(queryDTO);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "查询企业详情 @author 开云")
 | 
			
		||||
    @GetMapping("/oa/enterprise/get/{enterpriseId}")
 | 
			
		||||
    @SaAuth
 | 
			
		||||
    public ResponseDTO<EnterpriseVO> getDetail(@PathVariable Long enterpriseId) {
 | 
			
		||||
        return ResponseDTO.ok(enterpriseService.getDetail(enterpriseId));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "新建企业 @author 开云")
 | 
			
		||||
    @PostMapping("/oa/enterprise/create")
 | 
			
		||||
    @SaAuth
 | 
			
		||||
    public ResponseDTO<String> createEnterprise(@RequestBody @Valid EnterpriseCreateForm createVO) {
 | 
			
		||||
        RequestUser requestUser = SmartRequestUtil.getUser();
 | 
			
		||||
        createVO.setCreateUserId(requestUser.getUserId());
 | 
			
		||||
@@ -64,21 +60,18 @@ public class EnterpriseController {
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "编辑企业 @author 开云")
 | 
			
		||||
    @PostMapping("/oa/enterprise/update")
 | 
			
		||||
    @SaAuth
 | 
			
		||||
    public ResponseDTO<String> updateEnterprise(@RequestBody @Valid EnterpriseUpdateForm updateVO) {
 | 
			
		||||
        return enterpriseService.updateEnterprise(updateVO);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "删除企业 @author 开云")
 | 
			
		||||
    @GetMapping("/oa/enterprise/delete/{enterpriseId}")
 | 
			
		||||
    @SaAuth
 | 
			
		||||
    public ResponseDTO<String> deleteEnterprise(@PathVariable Long enterpriseId) {
 | 
			
		||||
        return enterpriseService.deleteEnterprise(enterpriseId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "企业列表查询 @author 开云")
 | 
			
		||||
    @GetMapping("/oa/enterprise/query/list")
 | 
			
		||||
    @SaAuth
 | 
			
		||||
    public ResponseDTO<List<EnterpriseListVO>> queryList(@RequestParam(value = "type", required = false) Integer type) {
 | 
			
		||||
        return enterpriseService.queryList(type);
 | 
			
		||||
    }
 | 
			
		||||
@@ -86,21 +79,18 @@ public class EnterpriseController {
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "企业添加员工 @author 罗伊")
 | 
			
		||||
    @PostMapping("/oa/enterprise/employee/add")
 | 
			
		||||
    @SaAuth
 | 
			
		||||
    public ResponseDTO<String> addEmployee(@RequestBody @Valid EnterpriseEmployeeForm enterpriseEmployeeForm) {
 | 
			
		||||
        return enterpriseService.addEmployee(enterpriseEmployeeForm);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "查询企业全部员工 @author 罗伊")
 | 
			
		||||
    @PostMapping("/oa/enterprise/employee/list")
 | 
			
		||||
    @SaAuth
 | 
			
		||||
    public ResponseDTO<List<EnterpriseEmployeeVO>> employeeList(@RequestBody @Valid List<Long> enterpriseIdList) {
 | 
			
		||||
        return ResponseDTO.ok(enterpriseService.employeeList(enterpriseIdList));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "分页查询企业员工 @author 卓大")
 | 
			
		||||
    @PostMapping("/oa/enterprise/employee/queryPage")
 | 
			
		||||
    @SaAuth
 | 
			
		||||
    public ResponseDTO<PageResult<EnterpriseEmployeeVO>> queryPageEmployeeList(@RequestBody @Valid EnterpriseEmployeeQueryForm queryForm) {
 | 
			
		||||
        return ResponseDTO.ok(enterpriseService.queryPageEmployeeList(queryForm));
 | 
			
		||||
    }
 | 
			
		||||
@@ -108,7 +98,6 @@ public class EnterpriseController {
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "企业删除员工 @author 罗伊")
 | 
			
		||||
    @PostMapping("/oa/enterprise/employee/delete")
 | 
			
		||||
    @SaAuth
 | 
			
		||||
    public ResponseDTO<String> deleteEmployee(@RequestBody @Valid EnterpriseEmployeeForm enterpriseEmployeeForm) {
 | 
			
		||||
        return enterpriseService.deleteEmployee(enterpriseEmployeeForm);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,6 @@ import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.*;
 | 
			
		||||
import net.lab1024.sa.admin.module.business.oa.notice.service.NoticeEmployeeService;
 | 
			
		||||
import net.lab1024.sa.admin.module.business.oa.notice.service.NoticeService;
 | 
			
		||||
import net.lab1024.sa.admin.module.business.oa.notice.service.NoticeTypeService;
 | 
			
		||||
import net.lab1024.sa.common.common.annoation.SaAuth;
 | 
			
		||||
import net.lab1024.sa.common.common.domain.PageResult;
 | 
			
		||||
import net.lab1024.sa.common.common.domain.ResponseDTO;
 | 
			
		||||
import net.lab1024.sa.common.common.util.SmartRequestUtil;
 | 
			
		||||
@@ -73,7 +72,6 @@ public class NoticeController {
 | 
			
		||||
 | 
			
		||||
    @ApiOperation("【管理】通知公告-分页查询 @author 卓大")
 | 
			
		||||
    @PostMapping("/oa/notice/query")
 | 
			
		||||
    @SaAuth
 | 
			
		||||
    public ResponseDTO<PageResult<NoticeVO>> query(@RequestBody @Valid NoticeQueryForm queryForm) {
 | 
			
		||||
        return ResponseDTO.ok(noticeService.query(queryForm));
 | 
			
		||||
    }
 | 
			
		||||
@@ -81,7 +79,6 @@ public class NoticeController {
 | 
			
		||||
    @ApiOperation("【管理】通知公告-添加 @author 卓大")
 | 
			
		||||
    @PostMapping("/oa/notice/add")
 | 
			
		||||
    @RepeatSubmit
 | 
			
		||||
    @SaAuth
 | 
			
		||||
    public ResponseDTO<String> add(@RequestBody @Valid NoticeAddForm addForm) {
 | 
			
		||||
        addForm.setCreateUserId(SmartRequestUtil.getUserId());
 | 
			
		||||
        return noticeService.add(addForm);
 | 
			
		||||
@@ -90,21 +87,18 @@ public class NoticeController {
 | 
			
		||||
    @ApiOperation("【管理】通知公告-更新 @author 卓大")
 | 
			
		||||
    @PostMapping("/oa/notice/update")
 | 
			
		||||
    @RepeatSubmit
 | 
			
		||||
    @SaAuth
 | 
			
		||||
    public ResponseDTO<String> update(@RequestBody @Valid NoticeUpdateForm updateForm) {
 | 
			
		||||
        return noticeService.update(updateForm);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation("【管理】通知公告-更新详情 @author 卓大")
 | 
			
		||||
    @GetMapping("/oa/notice/getUpdateVO/{noticeId}")
 | 
			
		||||
    @SaAuth
 | 
			
		||||
    public ResponseDTO<NoticeUpdateFormVO> getUpdateFormVO(@PathVariable Long noticeId) {
 | 
			
		||||
        return ResponseDTO.ok(noticeService.getUpdateFormVO(noticeId));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation("【管理】通知公告-删除 @author 卓大")
 | 
			
		||||
    @GetMapping("/oa/notice/delete/{noticeId}")
 | 
			
		||||
    @SaAuth
 | 
			
		||||
    public ResponseDTO<String> delete(@PathVariable Long noticeId) {
 | 
			
		||||
        return noticeService.delete(noticeId);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
 | 
			
		||||
import io.swagger.annotations.ApiModelProperty;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import net.lab1024.sa.admin.module.system.menu.domain.vo.MenuVO;
 | 
			
		||||
import net.lab1024.sa.common.common.domain.RequestUser;
 | 
			
		||||
import net.lab1024.sa.common.common.enumeration.GenderEnum;
 | 
			
		||||
import net.lab1024.sa.common.common.enumeration.UserTypeEnum;
 | 
			
		||||
import net.lab1024.sa.common.common.swagger.ApiModelPropertyEnum;
 | 
			
		||||
@@ -22,7 +21,7 @@ import java.util.List;
 | 
			
		||||
 * @Copyright 1024创新实验室 ( https://1024lab.net ),2012-2022
 | 
			
		||||
 */
 | 
			
		||||
@Data
 | 
			
		||||
public class LoginEmployeeDetail implements RequestUser {
 | 
			
		||||
public class LoginEmployeeDetail {
 | 
			
		||||
 | 
			
		||||
    @ApiModelProperty("token")
 | 
			
		||||
    private String token;
 | 
			
		||||
@@ -74,14 +73,4 @@ public class LoginEmployeeDetail implements RequestUser {
 | 
			
		||||
 | 
			
		||||
    @ApiModelProperty("请求user-agent")
 | 
			
		||||
    private String userAgent;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Long getUserId() {
 | 
			
		||||
        return employeeId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String getUserName() {
 | 
			
		||||
        return actualName;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
import org.springframework.util.CollectionUtils;
 | 
			
		||||
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
@@ -38,10 +39,6 @@ public class MenuService {
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private MenuDao menuDao;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private List<RequestUrlVO> authUrl;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 添加菜单
 | 
			
		||||
     *
 | 
			
		||||
@@ -284,7 +281,8 @@ public class MenuService {
 | 
			
		||||
     * @return
 | 
			
		||||
     */
 | 
			
		||||
    public ResponseDTO<List<RequestUrlVO>> getAuthUrl() {
 | 
			
		||||
        return ResponseDTO.ok(authUrl);
 | 
			
		||||
        // TODO listen
 | 
			
		||||
        return ResponseDTO.ok(Collections.emptyList());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -49,7 +49,7 @@
 | 
			
		||||
            </exclusions>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <!-- sa-token -->
 | 
			
		||||
        <!-- sa-token start -->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>cn.dev33</groupId>
 | 
			
		||||
            <artifactId>sa-token-spring-boot-starter</artifactId>
 | 
			
		||||
@@ -60,6 +60,13 @@
 | 
			
		||||
            <artifactId>sa-token-redis-jackson</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <!-- Sa-Token 整合 jwt -->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>cn.dev33</groupId>
 | 
			
		||||
            <artifactId>sa-token-jwt</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
        <!-- sa-token end -->
 | 
			
		||||
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.springframework.boot</groupId>
 | 
			
		||||
            <artifactId>spring-boot-starter-log4j2</artifactId>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,22 +0,0 @@
 | 
			
		||||
package net.lab1024.sa.common.common.annoation;
 | 
			
		||||
 | 
			
		||||
import java.lang.annotation.ElementType;
 | 
			
		||||
import java.lang.annotation.Retention;
 | 
			
		||||
import java.lang.annotation.RetentionPolicy;
 | 
			
		||||
import java.lang.annotation.Target;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 校验权限注解
 | 
			
		||||
 *
 | 
			
		||||
 * @Author 1024创新实验室: 罗伊
 | 
			
		||||
 * @Date 2022-05-30 21:22:12
 | 
			
		||||
 * @Wechat zhuoda1024
 | 
			
		||||
 * @Email lab1024@163.com
 | 
			
		||||
 * @Copyright 1024创新实验室 ( https://1024lab.net )
 | 
			
		||||
 */
 | 
			
		||||
@Retention(RetentionPolicy.RUNTIME)
 | 
			
		||||
@Target(ElementType.METHOD)
 | 
			
		||||
public @interface SaAuth {
 | 
			
		||||
 | 
			
		||||
    String saAuth = "saAuth";
 | 
			
		||||
}
 | 
			
		||||
@@ -32,7 +32,11 @@ public enum UserErrorCode implements ErrorCode {
 | 
			
		||||
 | 
			
		||||
    USER_STATUS_ERROR(30008, "用户状态异常"),
 | 
			
		||||
 | 
			
		||||
    FORM_REPEAT_SUBMIT(30009, "请勿重复提交");
 | 
			
		||||
    FORM_REPEAT_SUBMIT(30009, "请勿重复提交"),
 | 
			
		||||
 | 
			
		||||
    LOGIN_FROM_OTHER(30010, "您的账号已在其他地方登录"),
 | 
			
		||||
 | 
			
		||||
    ;
 | 
			
		||||
 | 
			
		||||
    private final int code;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,11 @@
 | 
			
		||||
package net.lab1024.sa.common.common.domain;
 | 
			
		||||
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import net.lab1024.sa.common.common.enumeration.UserTypeEnum;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 请求用户
 | 
			
		||||
 * 多系统用户 可以继承此类
 | 
			
		||||
 *
 | 
			
		||||
 * @Author 1024创新实验室-主任: 卓大
 | 
			
		||||
 * @Date 2021-12-21 19:55:07
 | 
			
		||||
@@ -11,39 +13,31 @@ import net.lab1024.sa.common.common.enumeration.UserTypeEnum;
 | 
			
		||||
 * @Email lab1024@163.com
 | 
			
		||||
 * @Copyright 1024创新实验室 ( https://1024lab.net )
 | 
			
		||||
 */
 | 
			
		||||
public interface RequestUser {
 | 
			
		||||
@Data
 | 
			
		||||
public class RequestUser {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 请求用户id
 | 
			
		||||
     *
 | 
			
		||||
     * @return
 | 
			
		||||
     * 当前请求用户id
 | 
			
		||||
     */
 | 
			
		||||
    Long getUserId();
 | 
			
		||||
    private Long userId;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 请求用户名称
 | 
			
		||||
     *
 | 
			
		||||
     * @return
 | 
			
		||||
     * 当前请求用户名称
 | 
			
		||||
     */
 | 
			
		||||
    String getUserName();
 | 
			
		||||
    private String userName;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取用户类型
 | 
			
		||||
     * 当前请求用户类型
 | 
			
		||||
     */
 | 
			
		||||
    UserTypeEnum getUserType();
 | 
			
		||||
    private UserTypeEnum userType;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取请求的IP
 | 
			
		||||
     *
 | 
			
		||||
     * @return
 | 
			
		||||
     * TODO listen 准备移除
 | 
			
		||||
     * 为了其他地方不报错
 | 
			
		||||
     */
 | 
			
		||||
    String getIp();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取请求 user-agent
 | 
			
		||||
     *
 | 
			
		||||
     * @return
 | 
			
		||||
     */
 | 
			
		||||
    String getUserAgent();
 | 
			
		||||
    @Deprecated
 | 
			
		||||
    private String ip;
 | 
			
		||||
 | 
			
		||||
    @Deprecated
 | 
			
		||||
    private String userAgent;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,15 @@
 | 
			
		||||
package net.lab1024.sa.common.common.interceptor;
 | 
			
		||||
 | 
			
		||||
import com.alibaba.fastjson.JSONObject;
 | 
			
		||||
import com.google.common.collect.Lists;
 | 
			
		||||
import net.lab1024.sa.common.common.annoation.NoNeedLogin;
 | 
			
		||||
import net.lab1024.sa.common.common.code.UserErrorCode;
 | 
			
		||||
import net.lab1024.sa.common.common.constant.RequestHeaderConst;
 | 
			
		||||
import net.lab1024.sa.common.common.constant.StringConst;
 | 
			
		||||
import net.lab1024.sa.common.common.domain.RequestUser;
 | 
			
		||||
import net.lab1024.sa.common.common.domain.ResponseDTO;
 | 
			
		||||
import net.lab1024.sa.common.common.util.SmartRequestUtil;
 | 
			
		||||
import org.apache.commons.lang3.StringUtils;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.HttpMethod;
 | 
			
		||||
import org.springframework.http.HttpStatus;
 | 
			
		||||
import org.springframework.util.CollectionUtils;
 | 
			
		||||
@@ -19,7 +20,6 @@ import javax.servlet.http.HttpServletRequest;
 | 
			
		||||
import javax.servlet.http.HttpServletResponse;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.function.Function;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 抽象拦截器
 | 
			
		||||
@@ -32,16 +32,12 @@ import java.util.function.Function;
 | 
			
		||||
 */
 | 
			
		||||
public abstract class AbstractInterceptor implements HandlerInterceptor {
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private List<String> ignoreUrlList;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Token获取用户信息
 | 
			
		||||
     *
 | 
			
		||||
     * @return
 | 
			
		||||
     */
 | 
			
		||||
    protected abstract Function<String, RequestUser> userFunction();
 | 
			
		||||
    public abstract RequestUser checkTokenAndGetUser();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 拦截路径
 | 
			
		||||
@@ -56,6 +52,12 @@ public abstract class AbstractInterceptor implements HandlerInterceptor {
 | 
			
		||||
     * @return
 | 
			
		||||
     */
 | 
			
		||||
    protected List<String> getIgnoreUrlList() {
 | 
			
		||||
        List<String> ignoreUrlList = Lists.newArrayList();
 | 
			
		||||
        ignoreUrlList.add("/swagger-ui.html");
 | 
			
		||||
        ignoreUrlList.add("/swagger-resources/**");
 | 
			
		||||
        ignoreUrlList.add("/webjars/**");
 | 
			
		||||
        ignoreUrlList.add("/druid/**");
 | 
			
		||||
        ignoreUrlList.add("/*/api-docs");
 | 
			
		||||
        return ignoreUrlList;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -83,7 +85,7 @@ public abstract class AbstractInterceptor implements HandlerInterceptor {
 | 
			
		||||
        //放行的Uri前缀
 | 
			
		||||
        String uri = request.getRequestURI();
 | 
			
		||||
        String contextPath = request.getContextPath();
 | 
			
		||||
        String target = uri.replaceFirst(contextPath, "");
 | 
			
		||||
        String target = uri.replaceFirst(contextPath, StringConst.EMPTY);
 | 
			
		||||
        if (this.contain(this.getIgnoreUrlList(), target)) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
@@ -95,9 +97,9 @@ public abstract class AbstractInterceptor implements HandlerInterceptor {
 | 
			
		||||
        String xAccessToken = StringUtils.isNotBlank(xRequestToken) ? xRequestToken : xHeaderToken;
 | 
			
		||||
        // 包含token 则获取用户信息 并保存
 | 
			
		||||
        if (StringUtils.isNotBlank(xAccessToken)) {
 | 
			
		||||
            RequestUser requestUser = userFunction().apply(xAccessToken);
 | 
			
		||||
            RequestUser requestUser = this.checkTokenAndGetUser();
 | 
			
		||||
            if (requestUser != null) {
 | 
			
		||||
                // SmartRequestUtil.setRequestUser(requestUser);
 | 
			
		||||
                SmartRequestUtil.setUser(requestUser);
 | 
			
		||||
            }
 | 
			
		||||
            // 有token 无需登录
 | 
			
		||||
            if (null != noNeedLogin) {
 | 
			
		||||
 
 | 
			
		||||
@@ -14,9 +14,15 @@ import net.lab1024.sa.common.common.domain.RequestUser;
 | 
			
		||||
 */
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class SmartRequestUtil {
 | 
			
		||||
 | 
			
		||||
    private static final ThreadLocal<RequestUser> LOCAL = new ThreadLocal<>();
 | 
			
		||||
 | 
			
		||||
    public static void setUser(RequestUser requestUser) {
 | 
			
		||||
        LOCAL.set(requestUser);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static RequestUser getUser() {
 | 
			
		||||
        // TODO listen
 | 
			
		||||
        return null;
 | 
			
		||||
        return LOCAL.get();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Long getUserId() {
 | 
			
		||||
@@ -25,7 +31,7 @@ public class SmartRequestUtil {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void remove() {
 | 
			
		||||
        // TODO listen
 | 
			
		||||
        LOCAL.remove();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,6 @@ import net.lab1024.sa.common.common.interceptor.AbstractInterceptor;
 | 
			
		||||
import org.apache.commons.collections4.CollectionUtils;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.context.annotation.Configuration;
 | 
			
		||||
import org.springframework.web.servlet.HandlerInterceptor;
 | 
			
		||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
 | 
			
		||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
 | 
			
		||||
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
 | 
			
		||||
@@ -25,7 +24,7 @@ import java.util.List;
 | 
			
		||||
public class MvcConfig implements WebMvcConfigurer {
 | 
			
		||||
 | 
			
		||||
    @Autowired(required = false)
 | 
			
		||||
    private List<HandlerInterceptor> interceptorList;
 | 
			
		||||
    private List<AbstractInterceptor> interceptorList;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void addInterceptors (InterceptorRegistry registry) {
 | 
			
		||||
@@ -33,7 +32,7 @@ public class MvcConfig implements WebMvcConfigurer {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        interceptorList.forEach(e->{
 | 
			
		||||
            registry.addInterceptor(e).addPathPatterns("/**");
 | 
			
		||||
            registry.addInterceptor(e).addPathPatterns(e.pathPatterns());
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,150 +0,0 @@
 | 
			
		||||
package net.lab1024.sa.common.config;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.util.StrUtil;
 | 
			
		||||
import com.google.common.collect.Lists;
 | 
			
		||||
import com.google.common.collect.Maps;
 | 
			
		||||
import io.swagger.annotations.ApiOperation;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import net.lab1024.sa.common.common.annoation.NoNeedLogin;
 | 
			
		||||
import net.lab1024.sa.common.common.annoation.SaAuth;
 | 
			
		||||
import net.lab1024.sa.common.common.domain.RequestUrlVO;
 | 
			
		||||
import org.apache.commons.collections4.CollectionUtils;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.context.annotation.Bean;
 | 
			
		||||
import org.springframework.context.annotation.Configuration;
 | 
			
		||||
import org.springframework.web.method.HandlerMethod;
 | 
			
		||||
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
 | 
			
		||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
 | 
			
		||||
 | 
			
		||||
import java.lang.reflect.Method;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * url配置
 | 
			
		||||
 *
 | 
			
		||||
 * @Author 1024创新实验室: 罗伊
 | 
			
		||||
 * @Date 2022-05-30 21:22:12
 | 
			
		||||
 * @Wechat zhuoda1024
 | 
			
		||||
 * @Email lab1024@163.com
 | 
			
		||||
 * @Copyright 1024创新实验室 ( https://1024lab.net )
 | 
			
		||||
 */
 | 
			
		||||
@Configuration
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class UrlConfig {
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private RequestMappingHandlerMapping requestMappingHandlerMapping;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取每个方法的请求路径
 | 
			
		||||
     *
 | 
			
		||||
     * @return
 | 
			
		||||
     */
 | 
			
		||||
    @Bean
 | 
			
		||||
    public Map<Method, Set<String>> methodUrlMap() {
 | 
			
		||||
        Map<Method, Set<String>> methodUrlMap = Maps.newHashMap();
 | 
			
		||||
        //获取url与类和方法的对应信息
 | 
			
		||||
        Map<RequestMappingInfo, HandlerMethod> map = requestMappingHandlerMapping.getHandlerMethods();
 | 
			
		||||
        for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : map.entrySet()) {
 | 
			
		||||
            RequestMappingInfo requestMappingInfo = entry.getKey();
 | 
			
		||||
 | 
			
		||||
            Set<String> urls = requestMappingInfo.getPatternsCondition().getPatterns();
 | 
			
		||||
            if (CollectionUtils.isEmpty(urls)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            HandlerMethod handlerMethod = entry.getValue();
 | 
			
		||||
            methodUrlMap.put(handlerMethod.getMethod(), urls);
 | 
			
		||||
        }
 | 
			
		||||
        return methodUrlMap;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 需要进行url权限校验的方法
 | 
			
		||||
     *
 | 
			
		||||
     * @param methodUrlMap
 | 
			
		||||
     * @return
 | 
			
		||||
     */
 | 
			
		||||
    @Bean
 | 
			
		||||
    public List<RequestUrlVO> authUrl(Map<Method, Set<String>> methodUrlMap) {
 | 
			
		||||
        List<RequestUrlVO> authUrlList = Lists.newArrayList();
 | 
			
		||||
        for (Map.Entry<Method, Set<String>> entry : methodUrlMap.entrySet()) {
 | 
			
		||||
            Method method = entry.getKey();
 | 
			
		||||
            SaAuth saAuth = method.getAnnotation(SaAuth.class);
 | 
			
		||||
            if (null == saAuth) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            List<RequestUrlVO> requestUrlList = this.buildRequestUrl(method, entry.getValue());
 | 
			
		||||
            authUrlList.addAll(requestUrlList);
 | 
			
		||||
        }
 | 
			
		||||
        log.info("需要权限校验的URL:{}", authUrlList.stream().map(e -> e.getUrl()).collect(Collectors.toList()));
 | 
			
		||||
        return authUrlList;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private List<RequestUrlVO> buildRequestUrl(Method method, Set<String> urlSet) {
 | 
			
		||||
        List<RequestUrlVO> requestUrlList = Lists.newArrayList();
 | 
			
		||||
        if (CollectionUtils.isEmpty(urlSet)) {
 | 
			
		||||
            return requestUrlList;
 | 
			
		||||
        }
 | 
			
		||||
        //url对应的方法名称
 | 
			
		||||
        String className = method.getDeclaringClass().getName();
 | 
			
		||||
        String methodName = method.getName();
 | 
			
		||||
        List<String> list = StrUtil.split(className, ".");
 | 
			
		||||
        String controllerName = list.get(list.size() - 1);
 | 
			
		||||
        String name = controllerName + "." + methodName;
 | 
			
		||||
        //swagger 说明信息
 | 
			
		||||
        String methodComment = null;
 | 
			
		||||
        ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
 | 
			
		||||
        if (apiOperation != null) {
 | 
			
		||||
            methodComment = apiOperation.value();
 | 
			
		||||
        }
 | 
			
		||||
        for (String url : urlSet) {
 | 
			
		||||
            RequestUrlVO requestUrlVO = new RequestUrlVO();
 | 
			
		||||
            requestUrlVO.setUrl(url);
 | 
			
		||||
            requestUrlVO.setName(name);
 | 
			
		||||
            requestUrlVO.setComment(methodComment);
 | 
			
		||||
            requestUrlList.add(requestUrlVO);
 | 
			
		||||
        }
 | 
			
		||||
        return requestUrlList;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取无需登录可以匿名访问的url信息
 | 
			
		||||
     *
 | 
			
		||||
     * @return
 | 
			
		||||
     */
 | 
			
		||||
    @Bean
 | 
			
		||||
    public List<String> noNeedLoginUrlList(Map<Method, Set<String>> methodUrlMap) {
 | 
			
		||||
        List<String> noNeedLoginUrlList = Lists.newArrayList();
 | 
			
		||||
        for (Map.Entry<Method, Set<String>> entry : methodUrlMap.entrySet()) {
 | 
			
		||||
            Method method = entry.getKey();
 | 
			
		||||
            NoNeedLogin noNeedLogin = method.getAnnotation(NoNeedLogin.class);
 | 
			
		||||
            if (null == noNeedLogin) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            noNeedLoginUrlList.addAll(entry.getValue());
 | 
			
		||||
        }
 | 
			
		||||
        log.info("不需要登录的URL:{}", noNeedLoginUrlList);
 | 
			
		||||
        return noNeedLoginUrlList;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取忽略的url信息
 | 
			
		||||
     *
 | 
			
		||||
     * @return
 | 
			
		||||
     */
 | 
			
		||||
    @Bean
 | 
			
		||||
    public List<String> ignoreUrlList() {
 | 
			
		||||
        List<String> ignoreUrlList = Lists.newArrayList();
 | 
			
		||||
        ignoreUrlList.add("/swagger-ui.html");
 | 
			
		||||
        ignoreUrlList.add("/swagger-resources/**");
 | 
			
		||||
        ignoreUrlList.add("/webjars/**");
 | 
			
		||||
        ignoreUrlList.add("/druid/**");
 | 
			
		||||
        ignoreUrlList.add("/*/api-docs");
 | 
			
		||||
        return ignoreUrlList;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,29 @@
 | 
			
		||||
package net.lab1024.sa.common.config.satoken;
 | 
			
		||||
 | 
			
		||||
import cn.dev33.satoken.jwt.StpLogicJwtForSimple;
 | 
			
		||||
import cn.dev33.satoken.stp.StpLogic;
 | 
			
		||||
import org.springframework.context.annotation.Bean;
 | 
			
		||||
import org.springframework.context.annotation.Configuration;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * sa token 配置
 | 
			
		||||
 *
 | 
			
		||||
 * @author: listen
 | 
			
		||||
 * @date: 2023/7/12 20:46
 | 
			
		||||
 */
 | 
			
		||||
@Configuration
 | 
			
		||||
public class SaTokenConfig {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 整合 jwt
 | 
			
		||||
     *
 | 
			
		||||
     * @return
 | 
			
		||||
     * @see <a>https://sa-token.cc/doc.html#/plugin/jwt-extend</a>
 | 
			
		||||
     */
 | 
			
		||||
    @Bean
 | 
			
		||||
    public StpLogic getStpLogicJwt() {
 | 
			
		||||
        // Simple 简单模式
 | 
			
		||||
        return new StpLogicJwtForSimple();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
package net.lab1024.sa.common.handler;
 | 
			
		||||
 | 
			
		||||
import cn.dev33.satoken.exception.NotLoginException;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import net.lab1024.sa.common.common.code.SystemErrorCode;
 | 
			
		||||
import net.lab1024.sa.common.common.code.UserErrorCode;
 | 
			
		||||
@@ -88,6 +89,34 @@ public class GlobalExceptionHandler {
 | 
			
		||||
        return ResponseDTO.error(SystemErrorCode.SYSTEM_ERROR, e.getMessage());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * sa-token 登录异常处理
 | 
			
		||||
     *
 | 
			
		||||
     * @param nle
 | 
			
		||||
     * @return
 | 
			
		||||
     * @throws Exception
 | 
			
		||||
     */
 | 
			
		||||
    @ResponseBody
 | 
			
		||||
    @ExceptionHandler(NotLoginException.class)
 | 
			
		||||
    public ResponseDTO<String> handlerNotLoginException(NotLoginException nle) {
 | 
			
		||||
        /**
 | 
			
		||||
         * 判断场景值 自己根据业务在下面 switch 添加分支判断
 | 
			
		||||
         * NotLoginException.NOT_TOKEN 无token
 | 
			
		||||
         * NotLoginException.INVALID_TOKEN token无效
 | 
			
		||||
         * NotLoginException.TOKEN_TIMEOUT token过期
 | 
			
		||||
         * NotLoginException.NO_PREFIX token缺少前缀
 | 
			
		||||
         * NotLoginException.KICK_OUT 已被踢下线
 | 
			
		||||
         * NotLoginException.TOKEN_FREEZE 已被冻结
 | 
			
		||||
         */
 | 
			
		||||
        switch (nle.getType()) {
 | 
			
		||||
            case NotLoginException.BE_REPLACED:
 | 
			
		||||
                // token 已被顶下线
 | 
			
		||||
                return ResponseDTO.error(UserErrorCode.LOGIN_FROM_OTHER);
 | 
			
		||||
            default:
 | 
			
		||||
                return ResponseDTO.error(UserErrorCode.LOGIN_STATE_INVALID);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 其他全部异常
 | 
			
		||||
     *
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@ package net.lab1024.sa.common.module.support.token;
 | 
			
		||||
 | 
			
		||||
import cn.dev33.satoken.stp.SaLoginModel;
 | 
			
		||||
import cn.dev33.satoken.stp.StpUtil;
 | 
			
		||||
import net.lab1024.sa.common.common.constant.StringConst;
 | 
			
		||||
import net.lab1024.sa.common.common.enumeration.UserTypeEnum;
 | 
			
		||||
import org.springframework.stereotype.Component;
 | 
			
		||||
 | 
			
		||||
@@ -19,9 +20,9 @@ import java.util.List;
 | 
			
		||||
@Component
 | 
			
		||||
public class TokenService {
 | 
			
		||||
 | 
			
		||||
    private static final String EXTRA_KEY_USER_NAME = "userName";
 | 
			
		||||
    public static final String EXTRA_KEY_USER_NAME = "userName";
 | 
			
		||||
 | 
			
		||||
    private static final String EXTRA_KEY_USER_TYPE = "userType";
 | 
			
		||||
    public static final String EXTRA_KEY_USER_TYPE = "userType";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 生成Token
 | 
			
		||||
@@ -55,7 +56,11 @@ public class TokenService {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String generateLoginId(Long userId, UserTypeEnum userType) {
 | 
			
		||||
        return userType.getValue() + "_" + userId;
 | 
			
		||||
        return userType.getValue() + StringConst.UNDERLINE + userId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Long getUserId(String loginId) {
 | 
			
		||||
        return Long.valueOf(loginId.substring(loginId.indexOf(StringConst.UNDERLINE) + 1));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -124,17 +124,19 @@ reload:
 | 
			
		||||
sa-token:
 | 
			
		||||
  # token 名称(同时也是 cookie 名称)
 | 
			
		||||
  token-name: x-access-token
 | 
			
		||||
  # token 前缀
 | 
			
		||||
  # token 前缀 例如:Bear
 | 
			
		||||
  token-prefix:
 | 
			
		||||
  # jwt秘钥
 | 
			
		||||
  jwt-secret-key: smart-admin
 | 
			
		||||
  # token 有效期(单位:秒) 默认30天,-1 代表永久有效
 | 
			
		||||
  timeout: 2592000
 | 
			
		||||
  # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
 | 
			
		||||
  active-timeout: 28800
 | 
			
		||||
  # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
 | 
			
		||||
  is-concurrent: false
 | 
			
		||||
  # 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
 | 
			
		||||
  # 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)(jwt模式下恒false)
 | 
			
		||||
  is-share: false
 | 
			
		||||
  # token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
 | 
			
		||||
  # token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)(jwt模式下无用)
 | 
			
		||||
  token-style: simple-uuid
 | 
			
		||||
  # 是否输出操作日志
 | 
			
		||||
  is-log: true
 | 
			
		||||
		Reference in New Issue
	
	Block a user