Spring Security实现接口放通的方法详解

网友投稿 293 2022-10-04

Spring Security实现接口放通的方法详解

目录1.SpringBoot版本2.实现思路3.实现过程3.1新建注解3.2新建请求枚举类3.3判断Controller方法上是否存在该注解3.4在SecurityConfig上进行策略的配置3.5在Controller方法上应用3.6效果展示

在用Spring Security项目开发中,有时候需要放通某一个接口时,我们需要在配置中把接口地址配置上,这样做有时候显得麻烦,而且不够优雅。我们能不能通过一个注解的方式,在需要放通的接口上加上该注解,这样接口就能放通了。答案肯定是可以的啦,今天我们一起来看看实现过程吧。

1.SpringBoot版本

本文基于的Spring Boot的版本是2.6.7

2.实现思路

新建一个AnonymousAccess注解,该注解是应用于Controller方法上的

新建一个存放所有请求方式的枚举类

通过判断Controller方法上是否存在该注解

在SecurityConfig上进行策略的配置

3.实现过程

3.1新建注解

@Inherited

@Documented

@Target({ElementType.METHOD,ElementType.ANNOTATION_TYPE})

@Retention(RetentionPolicy.RUNTIME)

public @interface AnonymousAccess {

}

3.2新建请求枚举类

该类是存放所有的请求类型的,代码如下:

@Getter

@AllArgsConstructor

public enum RequestMethodEnum {

/**

* 搜寻 @AnonymousGetMapping

*/

GET("GET"),

/**

* 搜寻 @AnonymousPostMapping

*/

POST("POST"),

/**

* 搜寻 @AnonymousPutMapping

*/

PUT("PUT"),

/**

* 搜寻 @AnonymousPatchMapping

*/

PATCH("PATCH"),

/**

* 搜寻 @AnonymousDeleteMapping

*/

DELETE("DELETE"),

/**

* 否则就是所有 Request 接口都放行

*/

ALL("All");

/**

* Request 类型

*/

private final String type;

public static RequestMethodEnum find(String type) {

for (RequestMethodEnum value : RequestMethodEnum.values()) {

if (value.getType().equals(type)) {

return value;

}

}

return ALL;

}

}

3.3判断Controller方法上是否存在该注解

在SecurityConfig类中定义一个私有方法getAnonymousUrl,该方法主要作用是判断controller那些方法加上了AnonymousAccess的注解

private Map> getAnonymousUrl(Map handlerMethodMap) {

Map> anonymousUrls = new HashMap<>(8);

Set get = new HashSet<>();

Set post = new HashSet<>();

Set put = new HashSet<>();

Set patch = new HashSet<>();

Set delete = new HashSethttp://<>();

Set all = new HashSet<>();

for (Map.Entry infoEntry : handlerMethodMap.entrySet()) {

HandlerMethod handlerMethod = infoEntry.getValue();

AnonymousAccess anonymousAccess = handlerMethod.getMethodAnnotation(AnonymousAccess.class);

if (null != anonymousAccess) {

List requestMethods = new ArrayList<>(infoEntry.getKey().getMethodsCondition().getMethods());

RequestMethodEnum request = RetMmcPquestMethodEnum.find(requestMethods.size() == 0 ? RequestMethodEnum.ALL.getType() :http:// requestMethods.get(0).name());

switch (Objects.requireNonNull(request)) {

case GET:

get.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());

break;

case POST:

post.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());

break;

case PUT:

put.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());

break;

case PATCH:

patch.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());

break;

case DELETE:

delete.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());

break;

default:

all.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());

break;

}

}

}

anonymousUrls.put(RequestMethodEnum.GET.getType(), get);

anonymousUrls.put(RequestMethodEnum.POST.getType(), post);

anonymousUrls.put(RequestMethodEnum.PUT.getType(), put);

anonymousUrls.put(RequestMethodEnum.PATCH.getType(), patch);

anonymousUrls.put(RequestMethodEnum.DELETE.getType(), delete);

anonymousUrls.put(RequestMethodEnum.ALL.getType(), all);

return anonymousUrls;

}

3.4在SecurityConfig上进行策略的配置

通过一个SpringUtil工具类获取到requestMappingHandlerMapping的Bean,然后通过getAnonymousUrl方法把标注AnonymousAccess接口找出来。最后,通过antMatchers细腻化到每个 Request 类型。

@Override

protected void configure(HttpSecurity httpSecurity) throws Exception {

// 搜寻匿名标记 url: @AnonymousAccess

RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping) SpringUtil.getBean("requestMappingHandlerMapping");

Map handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods();

// 获取匿名标记

Map> anonymousUrls = getAnonymousUrl(handlerMethodMap);

httpSecurity

//禁用CSRF

.csrf().disable()

.authorizeRequests()

// 自定义匿名访问所有url放行:细腻化到每个 Request 类型

// GET

.antMatchers(HttpMethod.GET,anonymousUrls.get(RequestMethodEnum.GET.getType()).toArray(new String[0])).permitAll()

// POST

.antMatchers(HttpMethod.POST,anonymousUrls.get(RequestMethodEnum.POST.getType()).toArray(new String[0])).permitAll()

// PUT

.antMatchers(HttpMethod.PUT,anonymousUrls.get(RequestMethodEnum.PUT.getType()).toArray(new String[0])).permitAll()

// PATCH

.antMatchers(HttpMethod.PATCH,anonymousUrls.get(RequestMethodEnum.PATCH.getType()).toArray(new String[0])).permitAll()

// DELETE

.antMatchers(HttpMethod.DELETE,anonymousUrls.get(RequestMethodEnum.DELETE.getType()).toArray(new String[0])).permitAll()

// 所有类型的接口都放行

.antMatchers(anonymousUrls.get(RequestMethodEnum.ALL.getType()).toArray(new String[0])).permitAll()

// 所有请求都需要认证

.anyRequest().authenticated();

}

3.5在Controller方法上应用

在Controller上把需要的放通的接口上加上注解,即可不需要认证就可以访问了,是不是很方便呢。例如,验证码不需要认证访问的,代码如下:

@ApiOperation(value = "获取验证码", notes = "获取验证码")

@AnonymousAccess

@GetMapping("/code")

public Object getCode(){

Captcha captcha = loginProperties.getCaptcha();

String uuid = "code-key-"+IdUtil.simpleUUID();

//当验证码类型为 arithmetic时且长度 >= 2 时,captcha.text()的结果有几率为浮点型

String captchaValue = captcha.text();

if(captcha.getCharType()-1 == LoginCodeEnum.ARITHMETIC.ordinal() && captchaValue.contains(".")){

captchaValue = captchaValue.split("\\.")[0];

}

// 保存

redisUtils.set(uuid,captchaValue,loginProperties.getLoginCode().getExpiration(), TimeUnit.MINUTES);

// 验证码信息

Map imgResult = new HashMap(2){{

put("img",captcha.toBase64());

put("uuid",uuid);

}};

return imgResult;

}

3.6效果展示

以上就是Spring Security实现接口放通的方法详解的详细内容,更多关于Spring Security接口放通的资料请关注我们其它相关文章!

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Office365 如何导出云用户的邮箱数据pst
下一篇:Office365 合规性管理配置介绍
相关文章

 发表评论

暂时没有评论,来抢沙发吧~