提交 46b3828b 作者: 方治民

feat: 新增二级认证接口及示例

上级 81c4cf7d
/* (C) 2021 YiRing, Inc. */
package com.yiring.app.config;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.*;
import com.yiring.common.core.I18n;
import com.yiring.common.core.Result;
import com.yiring.common.core.Status;
......@@ -47,7 +47,7 @@ public class GlobalExceptionHandler {
* @return 统一的校验失败信息 {@link Status#EXPECTATION_FAILED
*/
@ExceptionHandler(
value = { BindException.class, MethodArgumentNotValidException.class, ConstraintViolationException.class }
{ BindException.class, MethodArgumentNotValidException.class, ConstraintViolationException.class }
)
public Result<String> bindErrorHandler(Exception e) {
String details = null;
......@@ -107,6 +107,30 @@ public class GlobalExceptionHandler {
}
/**
* 1. 二级认证失败异常
* 2. 角色条件不满足
* 3. 权限条件不满足
* 4. HTTP Basic 验证不通过
* 5. 用户被禁止访问该服务
* 6. API 被禁用
*
* @return 异常信息反馈 {@link Status#FORBIDDEN
*/
@ExceptionHandler(
{
NotSafeException.class,
NotRoleException.class,
NotPermissionException.class,
NotBasicAuthException.class,
DisableServiceException.class,
ApiDisabledException.class,
}
)
public Result<String> notSafeErrorHandler() {
return Result.no(Status.FORBIDDEN);
}
/**
* 自定义业务异常
*/
@ExceptionHandler(BusinessException.class)
......@@ -125,9 +149,7 @@ public class GlobalExceptionHandler {
/**
* 取消请求异常(忽略)
*/
@ExceptionHandler(
value = { ClientAbortException.class, AbortException.class, HttpMessageNotWritableException.class }
)
@ExceptionHandler({ ClientAbortException.class, AbortException.class, HttpMessageNotWritableException.class })
public void clientAbortExceptionHandler() {}
/**
......
......@@ -2,6 +2,7 @@
package com.yiring.app.web.example;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckSafe;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.yiring.app.domain.user.UserExtension;
import com.yiring.app.domain.user.UserExtensionRepository;
......@@ -64,7 +65,7 @@ public class ExampleController {
@ApiOperation("测试失败")
@GetMapping("fail")
public Result<String> fail() {
throw BusinessException.i18n("Code.100000");
throw BusinessException.i18n("Code.1");
}
@SaCheckLogin
......@@ -94,6 +95,7 @@ public class ExampleController {
FileUtils.download(response, resource.getFile());
}
@SaCheckSafe
@SaCheckLogin
@ApiOperation("查询用户属性")
@GetMapping("findUserExtensionInfo")
......
......@@ -24,6 +24,7 @@ public class SaTokenConfigure implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册 Sa-Token 路由拦截器
// 可搭配使用注解实现鉴权: https://sa-token.dev33.cn/doc.html#/use/at-check
registry
.addInterceptor(
new SaInterceptor(handle -> {
......
/* (C) 2021 YiRing, Inc. */
package com.yiring.auth.param.auth;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serial;
import java.io.Serializable;
import javax.validation.constraints.NotEmpty;
import lombok.*;
import lombok.experimental.FieldDefaults;
/**
* 安全校验参数
*
* @author ifzm
* @version 0.1
* 2019/5/28 22:11
*/
@ApiModel("SafeParam")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
public class SafeParam implements Serializable {
@Serial
private static final long serialVersionUID = 9106494470582579138L;
@ApiModelProperty(value = "密码", example = "123456", required = true)
@NotEmpty(message = "密码不能为空")
String password;
}
/* (C) 2022 YiRing, Inc. */
package com.yiring.auth.web.auth;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil;
......@@ -9,6 +10,8 @@ import com.yiring.auth.domain.user.User;
import com.yiring.auth.domain.user.UserRepository;
import com.yiring.auth.param.auth.LoginParam;
import com.yiring.auth.param.auth.RegisterParam;
import com.yiring.auth.param.auth.SafeParam;
import com.yiring.auth.util.Auths;
import com.yiring.auth.vo.auth.LoginVo;
import com.yiring.common.core.Result;
import com.yiring.common.exception.BusinessException;
......@@ -16,9 +19,9 @@ import com.yiring.common.util.Commons;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import java.time.LocalDateTime;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Example;
import org.springframework.validation.annotation.Validated;
......@@ -42,10 +45,11 @@ import org.springframework.web.bind.annotation.RestController;
@Api(tags = "身份认证", description = "Auth")
@RestController
@RequestMapping("/auth/")
@RequiredArgsConstructor
public class AuthController {
@Resource
UserRepository userRepository;
final Auths auths;
final UserRepository userRepository;
@ApiOperation(value = "注册")
@PostMapping("register")
......@@ -123,7 +127,7 @@ public class AuthController {
return Result.ok(vo);
}
@ApiOperation(value = "检查登录状态")
@ApiOperation(value = "检查登录")
@GetMapping("valid")
public Result<Boolean> valid() {
return Result.ok(StpUtil.isLogin());
......@@ -135,4 +139,25 @@ public class AuthController {
StpUtil.logout();
return Result.ok();
}
/**
* 二次安全校验,搭配 @SaCheckSafe 实现对关键数据不可逆操作前的二次确认
* 默认安全时间: 120s
*
* @param param 用户密码
* @return
* @link { https://sa-token.dev33.cn/doc.html#/up/safe-auth }
*/
@SaCheckLogin
@ApiOperation(value = "安全校验")
@GetMapping("safe")
public Result<String> safe(@Valid SafeParam param) {
User user = auths.getLoginUser();
if (SaSecureUtil.sha256(param.getPassword()).equals(user.getPassword())) {
StpUtil.openSafe(120);
return Result.ok();
}
return Result.no();
}
}
......@@ -35,7 +35,7 @@ public enum Status {
UNAUTHORIZED(401, "Status.UNAUTHORIZED"),
/**
* Token 错误/失效
* 禁止访问(可能是二级认证失败)
*/
FORBIDDEN(403, "Status.FORBIDDEN"),
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论