Spring?Security實(shí)現(xiàn)接口放通的方法詳解
在用Spring Security項(xiàng)目開(kāi)發(fā)中,有時(shí)候需要放通某一個(gè)接口時(shí),我們需要在配置中把接口地址配置上,這樣做有時(shí)候顯得麻煩,而且不夠優(yōu)雅。我們能不能通過(guò)一個(gè)注解的方式,在需要放通的接口上加上該注解,這樣接口就能放通了。答案肯定是可以的啦,今天我們一起來(lái)看看實(shí)現(xiàn)過(guò)程吧。
1.SpringBoot版本
本文基于的Spring Boot的版本是2.6.7
2.實(shí)現(xiàn)思路
新建一個(gè)AnonymousAccess
注解,該注解是應(yīng)用于Controller
方法上的
新建一個(gè)存放所有請(qǐng)求方式的枚舉類
通過(guò)判斷Controller
方法上是否存在該注解
在SecurityConfig
上進(jìn)行策略的配置
3.實(shí)現(xiàn)過(guò)程
3.1新建注解
@Inherited @Documented @Target({ElementType.METHOD,ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface AnonymousAccess { }
3.2新建請(qǐng)求枚舉類
該類是存放所有的請(qǐng)求類型的,代碼如下:
@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
類中定義一個(gè)私有方法getAnonymousUrl
,該方法主要作用是判斷controller那些方法加上了AnonymousAccess
的注解
private Map<String, Set<String>> getAnonymousUrl(Map<RequestMappingInfo, HandlerMethod> handlerMethodMap) { Map<String, Set<String>> anonymousUrls = new HashMap<>(8); Set<String> get = new HashSet<>(); Set<String> post = new HashSet<>(); Set<String> put = new HashSet<>(); Set<String> patch = new HashSet<>(); Set<String> delete = new HashSet<>(); Set<String> all = new HashSet<>(); for (Map.Entry<RequestMappingInfo, HandlerMethod> infoEntry : handlerMethodMap.entrySet()) { HandlerMethod handlerMethod = infoEntry.getValue(); AnonymousAccess anonymousAccess = handlerMethod.getMethodAnnotation(AnonymousAccess.class); if (null != anonymousAccess) { List<RequestMethod> requestMethods = new ArrayList<>(infoEntry.getKey().getMethodsCondition().getMethods()); RequestMethodEnum request = RequestMethodEnum.find(requestMethods.size() == 0 ? RequestMethodEnum.ALL.getType() : 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上進(jìn)行策略的配置
通過(guò)一個(gè)SpringUtil
工具類獲取到requestMappingHandlerMapping
的Bean
,然后通過(guò)getAnonymousUrl
方法把標(biāo)注AnonymousAccess
接口找出來(lái)。最后,通過(guò)antMatchers
細(xì)膩化到每個(gè) Request 類型。
@Override protected void configure(HttpSecurity httpSecurity) throws Exception { // 搜尋匿名標(biāo)記 url: @AnonymousAccess RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping) SpringUtil.getBean("requestMappingHandlerMapping"); Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods(); // 獲取匿名標(biāo)記 Map<String, Set<String>> anonymousUrls = getAnonymousUrl(handlerMethodMap); httpSecurity //禁用CSRF .csrf().disable() .authorizeRequests() // 自定義匿名訪問(wèn)所有url放行:細(xì)膩化到每個(gè) 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() // 所有請(qǐng)求都需要認(rèn)證 .anyRequest().authenticated(); }
3.5在Controller方法上應(yīng)用
在Controller上把需要的放通的接口上加上注解,即可不需要認(rèn)證就可以訪問(wèn)了,是不是很方便呢。例如,驗(yàn)證碼不需要認(rèn)證訪問(wèn)的,代碼如下:
@ApiOperation(value = "獲取驗(yàn)證碼", notes = "獲取驗(yàn)證碼") @AnonymousAccess @GetMapping("/code") public Object getCode(){ Captcha captcha = loginProperties.getCaptcha(); String uuid = "code-key-"+IdUtil.simpleUUID(); //當(dāng)驗(yàn)證碼類型為 arithmetic時(shí)且長(zhǎng)度 >= 2 時(shí),captcha.text()的結(jié)果有幾率為浮點(diǎn)型 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); // 驗(yàn)證碼信息 Map<String,Object> imgResult = new HashMap<String,Object>(2){{ put("img",captcha.toBase64()); put("uuid",uuid); }}; return imgResult; }
3.6效果展示
以上就是Spring Security實(shí)現(xiàn)接口放通的方法詳解的詳細(xì)內(nèi)容,更多關(guān)于Spring Security接口放通的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Springdoc替換swagger的實(shí)現(xiàn)步驟分解
最近在spring看到的,spring要對(duì)api文檔動(dòng)手了,有些人說(shuō)swagger不好用,其實(shí)也沒(méi)那么不好用,有人說(shuō)代碼還是有點(diǎn)侵入性,這倒是真的,我剛試了springdoc可以說(shuō)還是有侵入性但是也可以沒(méi)有侵入性,這就看你對(duì)文檔有什么要求了2023-02-02解決SpringBoot打成jar運(yùn)行后無(wú)法讀取resources里的文件問(wèn)題
這篇文章主要介紹了解決SpringBoot打成jar運(yùn)行后無(wú)法讀取resources里的文件問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08使用maven profile指定配置文件打包適用多環(huán)境的方法
這篇文章主要介紹了使用maven profile指定配置文件打包適用多環(huán)境的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-08-08springmvc請(qǐng)求轉(zhuǎn)發(fā)和重定向問(wèn)題(攜帶參數(shù)和不攜帶參數(shù))
這篇文章主要介紹了springmvc請(qǐng)求轉(zhuǎn)發(fā)和重定向問(wèn)題(攜帶參數(shù)和不攜帶參數(shù)),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10Struts2攔截器Interceptor的原理與配置實(shí)例詳解
攔截器是一種AOP(面向切面編程)思想的編程方式.它提供一種機(jī)制是開(kāi)發(fā)者能夠把相對(duì)獨(dú)立的代碼抽離出來(lái),配置到Action前后執(zhí)行。下面這篇文章主要給大家介紹了關(guān)于Struts2攔截器Interceptor的原理與配置的相關(guān)資料,需要的朋友可以參考下。2017-11-11