Java注釈による権限管理
簡単な権限制御シーンで、ログインユーザidが知られており、そのユーザがデータベースに存在するかどうかを判断し、存在しない場合は何の操作も許可されていない.
Java注釈については、Javaカスタム注釈実装権限管理を参照してください.
インフラストラクチャの実装
各controllerメソッドにユーザー検証コードを追加します.これはメソッドレベルに制御できますが、各メソッドはこの重複論理を維持します.
ブロッキング実装
Springのブロッキング実装は,controllerメソッドに入る前に不正なユーザを早期にブロッキングする利点を増すが,異なるcontrollerクラスやメソッドの異なる権限を設計する場合,apiパスでしか区別できず不便である.
注記の実装
注記+ブロッキングの実装では、異なる粒度の権限制御を実現したり、権限を集中的に管理したりすることができます.定義権限列挙変数 定義注記 定義ブロッキング 登録ブロッキング 権限の追加
Java注釈については、Javaカスタム注釈実装権限管理を参照してください.
インフラストラクチャの実装
各controllerメソッドにユーザー検証コードを追加します.これはメソッドレベルに制御できますが、各メソッドはこの重複論理を維持します.
@RequestMapping(value = "/task/progress", method = RequestMethod.GET)
public RestRsp getLabelTaskProgress(
@RequestParam(name = "taskId", defaultValue = "-1") long taskId,
@Visitor long userId
) {
//
if (!labelService.checkUserValid(userId)) {
return RestRsp.success(new ListRsp());
}
//
...
return RestRsp.success(listRsp);
}
ブロッキング実装
Springのブロッキング実装は,controllerメソッドに入る前に不正なユーザを早期にブロッキングする利点を増すが,異なるcontrollerクラスやメソッドの異なる権限を設計する場合,apiパスでしか区別できず不便である.
@Slf4j
public class AuthInterceptor extends HandlerInterceptorAdapter {
private final static String LABEL_PATH_PATTERN = "^/*webapi/+label/*.*$";
private static final String ERROR_MSG = " , ";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) {
if (debugHost() && hasDebugParam(request)) {
return true;
}
String uri = request.getRequestURI();
log.info("uri:{}", uri);
String username = SsoUserInfo.getUserName();
if (Pattern.matches(LABEL_PATH_PATTERN, uri)) {
Set<String> managerSet = LABEL_MANAGER_SET.get();
if (!managerSet.contains(username)) {
throw new ServiceException(ErrorCode.PERMISSION_DENIED);
}
} else {
Set<String> userSet = USER_SET.get();
if (!userSet.contains(username)) {
throw ServiceException.ofMessage(ErrorCode.PERMISSION_DENIED, ERROR_MSG);
}
}
return true;
}
}
注記の実装
注記+ブロッキングの実装では、異なる粒度の権限制御を実現したり、権限を集中的に管理したりすることができます.
public enum AuthEnum {
USER_LABEL("label_user", " ", " "),
;
private String code;
private String desc;
private String info;
AuthEnum(String code, String desc, String info) {
this.code = code;
this.desc = desc;
this.info = info;
}
public String getCode() {
return this.code;
}
public String getDesc() {
return this.desc;
}
public String getInfo() {
return this.info;
}
}
@Documented
@Retention(value = RetentionPolicy.RUNTIME)
@Target({
ElementType.METHOD, ElementType.TYPE})
public @interface AuthAnn {
AuthEnum[] authType();
}
@Slf4j
@Component
public class AuthInterceptor extends HandlerInterceptorAdapter {
@Autowired
private LabelService labelService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) {
Long userId = SSOHelper.getUserId(request);
AuthAnn authAnn = ((HandlerMethod) handler).getMethodAnnotation(AuthAnn.class);
if (authAnn == null || ObjectUtils.isEmpty(authAnn.authType())) {
authAnn = ((HandlerMethod) handler).getBeanType().getAnnotation(AuthAnn.class);
}
if (authAnn == null || ObjectUtils.isEmpty(authAnn.authType())) {
return true;
}
//log.info("userId:{}", userId);
AuthEnum[] authEnums = authAnn.authType();
for (AuthEnum authEnum : authEnums) {
if (AuthEnum.USER_LABEL.equals(authEnum)) {
if (!labelService.checkUserExist(userId)) {
log.info("Invalid Label User, userId:{}", userId);
throw ServiceException.ofMessage(ErrorCode.PERMISSION_DENIED, authEnum.getInfo());
}
}
}
return true;
}
}
@Configuration
@Slf4j
public class ProphetInterceptorConfiguration implements WebMvcConfigurer {
@Autowired
private AuthInterceptor authInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
String[] paths = passportProperties.urlPaths();
registry.addInterceptor(AuthInterceptor).addPathPatterns(paths);
}
}
@Slf4j
@RestController
@RequestMapping("/api/label")
@AuthAnn(authType = AuthEnum.USER_LABEL)
public class LabelController {
}