久久r热视频,国产午夜精品一区二区三区视频,亚洲精品自拍偷拍,欧美日韩精品二区

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Spring Security 多過(guò)濾鏈的使用詳解

瀏覽:2日期:2023-07-03 09:40:59
目錄一、背景二、需求1、給客戶(hù)端使用的api2、給網(wǎng)站使用的api三、實(shí)現(xiàn)方案方案一:方案二四、實(shí)現(xiàn)1、app 端 Spring Security 的配置五、實(shí)現(xiàn)效果1、app 有權(quán)限訪問(wèn) api2、app 無(wú)權(quán)限訪問(wèn) api3、admin 用戶(hù)有權(quán)限訪問(wèn) 網(wǎng)站 api4、dev 用戶(hù)無(wú)權(quán)限訪問(wèn) 網(wǎng)站 api六、完整代碼一、背景

在我們實(shí)際的開(kāi)發(fā)過(guò)程中,有些時(shí)候可能存在這么一些情況,某些api 比如: /api/** 這些是給App端使用的,數(shù)據(jù)的返回都是以JSON的格式返回,且這些API的認(rèn)證方式都是使用的TOKEN進(jìn)行認(rèn)證。而除了 /api/** 這些API之外,都是給網(wǎng)頁(yè)端使用的,需要使用表單認(rèn)證,給前端返回的都是某個(gè)頁(yè)面。

二、需求1、給客戶(hù)端使用的api 攔截 /api/**所有的請(qǐng)求。 /api/**的所有請(qǐng)求都需要ROLE_ADMIN的角色。 從請(qǐng)求頭中獲取 token,只要獲取到token的值,就認(rèn)為認(rèn)證成功,并賦予ROLE_ADMIN到角色。 如果沒(méi)有權(quán)限,則給前端返回JSON對(duì)象 {message:'您無(wú)權(quán)限訪問(wèn)'} 訪問(wèn) /api/userInfo端點(diǎn) 請(qǐng)求頭攜帶 token 可以訪問(wèn)。請(qǐng)求頭不攜帶token不可以訪問(wèn)。2、給網(wǎng)站使用的api 攔截 所有的請(qǐng)求,但是不處理/api/**開(kāi)頭的請(qǐng)求。 所有的請(qǐng)求需要ROLE_ADMIN的權(quán)限。 沒(méi)有權(quán)限,需要使用表單登錄。 登錄成功后,訪問(wèn)了無(wú)權(quán)限的請(qǐng)求,直接跳轉(zhuǎn)到百度去。 構(gòu)建2個(gè)內(nèi)建的用戶(hù) 用戶(hù)一: admin/admin 擁有 ROLE_ADMIN 角色用戶(hù)二:dev/dev 擁有 ROLE_DEV 角色 訪問(wèn) /index 端點(diǎn) admin 用戶(hù)訪問(wèn),可以訪問(wèn)。dev 用戶(hù)訪問(wèn),不可以訪問(wèn),權(quán)限不夠。三、實(shí)現(xiàn)方案方案一:

直接拆成多個(gè)服務(wù),其中 /api/** 的成為一個(gè)服務(wù)。非/api/**的拆成另外一個(gè)服務(wù)。各個(gè)服務(wù)使用自己的配置,互不影響。

方案二

在同一個(gè)服務(wù)中編寫(xiě)。不同的請(qǐng)求使用不同的SecurityFilterChain來(lái)實(shí)現(xiàn)。

經(jīng)過(guò)考慮,此處采用方案二來(lái)實(shí)現(xiàn),因?yàn)榉桨敢缓?jiǎn)單,使用方案二實(shí)現(xiàn),也可以記錄下在同一個(gè)項(xiàng)目中 通過(guò)使用多條過(guò)濾器鏈,因?yàn)椴⒉皇撬械臅r(shí)候,都是可以分成多個(gè)項(xiàng)目的。

擴(kuò)展:

1、Spring Security SecurityFilterChain 的結(jié)構(gòu)

Spring Security 多過(guò)濾鏈的使用詳解

2、控制 SecurityFilterChain 的執(zhí)行順序

使用 org.springframework.core.annotation.Order 注解。

3、查看是怎樣選擇那個(gè) SecurityFilterChain 的

查看 org.springframework.web.filter.DelegatingFilterProxy#doFilter方法

四、實(shí)現(xiàn)1、app 端 Spring Security 的配置

package com.huan.study.security.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.core.annotation.Order;import org.springframework.http.HttpStatus;import org.springframework.http.MediaType;import org.springframework.security.authentication.TestingAuthenticationToken;import org.springframework.security.config.annotation.web.builders.HttpSecurity;import org.springframework.security.core.Authentication;import org.springframework.security.core.authority.AuthorityUtils;import org.springframework.security.core.context.SecurityContextHolder;import org.springframework.security.web.SecurityFilterChain;import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;import org.springframework.util.StringUtils;import javax.servlet.http.HttpServletRequest;import java.nio.charset.StandardCharsets;/** * 給 app 端用的 Security 配置 * * @author huan.fu 2021/7/13 - 下午9:06 */@Configurationpublic class AppSecurityConfig { /** * 處理 給 app(前后端分離) 端使用的過(guò)濾鏈 * 以 json 的數(shù)據(jù)格式返回給前端 */ @Bean @Order(1) public SecurityFilterChain appSecurityFilterChain(HttpSecurity http) throws Exception {// 只處理 /api 開(kāi)頭的請(qǐng)求return http.antMatcher('/api/**').authorizeRequests()// 所有以 /api 開(kāi)頭的請(qǐng)求都需要 ADMIN 的權(quán)限 .antMatchers('/api/**') .hasRole('ADMIN') .and()// 捕獲到異常,直接給前端返回 json 串.exceptionHandling() .authenticationEntryPoint((request, response, authException) -> {response.setStatus(HttpStatus.UNAUTHORIZED.value());response.setCharacterEncoding(StandardCharsets.UTF_8.name());response.setContentType(MediaType.APPLICATION_JSON.toString());response.getWriter().write('{'message:':'您無(wú)權(quán)訪問(wèn)01'}'); }) .accessDeniedHandler((request, response, accessDeniedException) -> {response.setStatus(HttpStatus.UNAUTHORIZED.value());response.setCharacterEncoding(StandardCharsets.UTF_8.name());response.setContentType(MediaType.APPLICATION_JSON.toString());response.getWriter().write('{'message:':'您無(wú)權(quán)訪問(wèn)02'}'); }) .and()// 用戶(hù)認(rèn)證.addFilterBefore((request, response, chain) -> { // 此處可以模擬從 token 中解析出用戶(hù)名、權(quán)限等 String token = ((HttpServletRequest) request).getHeader('token'); if (!StringUtils.hasText(token)) {chain.doFilter(request, response);return; } Authentication authentication = new TestingAuthenticationToken(token, null, AuthorityUtils.createAuthorityList('ROLE_ADMIN')); SecurityContextHolder.getContext().setAuthentication(authentication); chain.doFilter(request, response);}, UsernamePasswordAuthenticationFilter.class).build(); }}

2、網(wǎng)站端 Spring Secuirty 的配置

package com.huan.study.security.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.core.annotation.Order;import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;import org.springframework.security.config.annotation.web.builders.HttpSecurity;import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;import org.springframework.security.core.authority.AuthorityUtils;import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;import org.springframework.security.web.SecurityFilterChain;/** * 給 網(wǎng)站 應(yīng)用的安全配置 * * @author huan.fu 2021/7/14 - 上午9:09 */@Configurationpublic class WebSiteSecurityFilterChainConfig { /** * 處理 給 webSite(非前后端分離) 端使用的過(guò)濾鏈 * 以 頁(yè)面 的格式返回給前端 */ @Bean @Order(2) public SecurityFilterChain webSiteSecurityFilterChain(HttpSecurity http) throws Exception {AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);// 創(chuàng)建用戶(hù)authenticationManagerBuilder.inMemoryAuthentication().withUser('admin') .password(new BCryptPasswordEncoder().encode('admin')) .authorities(AuthorityUtils.commaSeparatedStringToAuthorityList('ROLE_ADMIN')) .and().withUser('dev') .password(new BCryptPasswordEncoder().encode('dev')) .authorities(AuthorityUtils.commaSeparatedStringToAuthorityList('ROLE_DEV')) .and().passwordEncoder(new BCryptPasswordEncoder());// 只處理 所有 開(kāi)頭的請(qǐng)求return http.antMatcher('/**').authorizeRequests()// 所有請(qǐng)求都必須要認(rèn)證才可以訪問(wèn) .anyRequest() .hasRole('ADMIN') .and()// 禁用csrf.csrf() .disable()// 啟用表單登錄.formLogin() .permitAll() .and()// 捕獲成功認(rèn)證后無(wú)權(quán)限訪問(wèn)異常,直接跳轉(zhuǎn)到 百度.exceptionHandling() .accessDeniedHandler((request, response, exception) -> {response.sendRedirect('http://www.baidu.com'); }) .and().build(); } /** * 忽略靜態(tài)資源 */ @Bean public WebSecurityCustomizer webSecurityCustomizer( ){return web -> web.ignoring().antMatchers('/**/js/**').antMatchers('/**/css/**'); }}

3、控制器寫(xiě)法

/** * 資源控制器 * * @author huan.fu 2021/7/13 - 下午9:33 */@Controllerpublic class ResourceController { /** * 返回用戶(hù)信息 */ @GetMapping('/api/userInfo') @ResponseBody public Authentication showUserInfoApi() {return SecurityContextHolder.getContext().getAuthentication(); } @GetMapping('/index') public String index(Model model){model.addAttribute('username','張三');return 'index'; }}

4、引入jar包

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId></dependency><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId></dependency>五、實(shí)現(xiàn)效果1、app 有權(quán)限訪問(wèn) api

Spring Security 多過(guò)濾鏈的使用詳解

2、app 無(wú)權(quán)限訪問(wèn) api

Spring Security 多過(guò)濾鏈的使用詳解

3、admin 用戶(hù)有權(quán)限訪問(wèn) 網(wǎng)站 api

Spring Security 多過(guò)濾鏈的使用詳解

4、dev 用戶(hù)無(wú)權(quán)限訪問(wèn) 網(wǎng)站 api

Spring Security 多過(guò)濾鏈的使用詳解

訪問(wèn)無(wú)權(quán)限的API直接跳轉(zhuǎn)到 百度 首頁(yè)。

六、完整代碼

https://gitee.com/huan1993/Spring-Security/tree/master/multi-security-filter-chain

到此這篇關(guān)于Spring Security 多過(guò)濾鏈的使用詳解的文章就介紹到這了,更多相關(guān)Spring Security 多過(guò)濾鏈 內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Spring
相關(guān)文章:
主站蜘蛛池模板: 屯门区| 察隅县| 大方县| 嘉兴市| 来宾市| 新竹市| 清镇市| 周宁县| 张掖市| 康定县| 淄博市| 福泉市| 永胜县| 辽宁省| 蒙阴县| 格尔木市| 安顺市| 梧州市| 嘉祥县| 天长市| 青田县| 汉阴县| 昆山市| 镇雄县| 宜黄县| 日照市| 博兴县| 霍林郭勒市| 万全县| 开阳县| 阿克苏市| 泸溪县| 长葛市| 阳泉市| 阿拉善左旗| 雅江县| 洞头县| 土默特左旗| 聂拉木县| 鱼台县| 潮州市|