利用@PreAuthorize注解自定义权限校验
使用场景:
由于项目中,需要对外开放接口,要求做请求头校验,不做其他权限控制.所以准备对开放的接口全部放行,不做登录校验.想到之前用这个注解来实现管理后台的权限校验,所以为了方便在需要对外开放的接口贴上注解即可.记录一下实现过程.
- 开启@EnableGlobalMethodSecurity(prePostEnabled = true)注解, 在继承 WebSecurityConfigurerAdapter 这个类的类上面贴上这个注解.并且prePostEnabled设置为true,@PreAuthorize这个注解才能生效,SpringSecurity默认是关闭注解功能的.
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements WebMvcConfigurer {....}
- 编写自定义的鉴权方法
// service取名sc是方便注解调用
@Service("sc")
@Slf4j
public class SginCheckService {
@Autowired
private PlatformManageService platformManageService;
public boolean checkSgin(){
HttpServletRequest request = UserContextHolder.getHttpServletRequest();
String appid = request.getHeader("appid");
String signature = request.getHeader("signature");
String timestamp = request.getHeader("timestamp");
//非crm管理平台
PlatformManage platformManage = platformManageService.getOne(Wrappers.<PlatformManage>lambdaQuery().eq(PlatformManage::getSourcetype, appid));
if (platformManage == null) {
log.error("平台不存在:" + appid);
//鉴权失败抛出自定义异常
throw new SginCheckException();
}
//校验签名
String secretKey = platformManage.getPrivateKey();
MD5 md5 = new MD5();
String lowerCase = md5.getMD5ofStr(appid + secretKey + timestamp).toLowerCase();
if (!lowerCase.equals(signature)) {
log.error("签名校验失败:" + "crm:" + lowerCase + ",接口:" + signature);
//鉴权失败抛出自定义异常
throw new SginCheckException();
}
//如果鉴权成功不return true 会报错.
return true;
}
}
- 创建自定义异常类
public class SginCheckException extends BaseException {
public SginCheckException() {
super();
}
public SginCheckException(String message) {
super(SystemErrorType.SIGNATURE_ERROR,message);
}
}
- 在统一异常处理类里面捕获异常类并做对应处理
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
/**
* 签名失败抛出异常处理
*
* @param e
* @return
*/
@ResponseBody
@ResponseStatus(HttpStatus.UNAUTHORIZED)
@ExceptionHandler(value = {SginCheckException.class})
public Result sginCheckException(SginCheckException e) {
return Result.fail(SystemErrorType.SIGNATURE_ERROR);
}
}
5.最后就是在需要鉴权的接口上贴上注解
// 调用方法语法 @beanname.methodname()
@ApiOperation(value = "会员注册", notes = "会员注册", httpMethod = "POST")
@PostMapping("/register")
@PreAuthorize("@sc.checkSgin()")
public Result register(@RequestBody @Valid MemberRegisterParam memberRegisterParam, HttpServletRequest request) {
log.error("会员注册:" + memberRegisterParam);
return memberService.register(memberRegisterParam, request);
}
结束语:
当然这个注解还有很多用法.我只是记录一下我的使用方法.不喜勿喷.