最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring Security 多過濾鏈的使用詳解

 更新時(shí)間:2021年07月15日 08:52:29   作者:huan_1993  
本文主要介紹了Spring Security 多過濾鏈的使用,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一、背景

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

二、需求

1、給客戶端使用的api

  • 攔截 /api/**所有的請(qǐng)求。
  • /api/**的所有請(qǐng)求都需要ROLE_ADMIN的角色。
  • 從請(qǐng)求頭中獲取 token,只要獲取到token的值,就認(rèn)為認(rèn)證成功,并賦予ROLE_ADMIN到角色。
  • 如果沒有權(quán)限,則給前端返回JSON對(duì)象 {message:"您無權(quán)限訪問"}
  • 訪問 /api/userInfo端點(diǎn)
    • 請(qǐng)求頭攜帶 token 可以訪問。
    • 請(qǐng)求頭不攜帶token不可以訪問。

2、給網(wǎng)站使用的api

  • 攔截 所有的請(qǐng)求,但是不處理/api/**開頭的請(qǐng)求。
  • 所有的請(qǐng)求需要ROLE_ADMIN的權(quán)限。
  • 沒有權(quán)限,需要使用表單登錄。
  • 登錄成功后,訪問了無權(quán)限的請(qǐng)求,直接跳轉(zhuǎn)到百度去。
  • 構(gòu)建2個(gè)內(nèi)建的用戶
    • 用戶一: admin/admin 擁有 ROLE_ADMIN 角色
    • 用戶二:dev/dev 擁有 ROLE_DEV 角色
  • 訪問 /index 端點(diǎn)
    • admin 用戶訪問,可以訪問。
    • dev 用戶訪問,不可以訪問,權(quán)限不夠。

三、實(shí)現(xiàn)方案

方案一:

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

方案二

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

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

擴(kuò)展:

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

SecurityFilterChain的結(jié)構(gòu)

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
 */
@Configuration
public class AppSecurityConfig {

    /**
     * 處理 給 app(前后端分離) 端使用的過濾鏈
     * 以 json 的數(shù)據(jù)格式返回給前端
     */
    @Bean
    @Order(1)
    public SecurityFilterChain appSecurityFilterChain(HttpSecurity http) throws Exception {
        // 只處理 /api 開頭的請(qǐng)求
        return http.antMatcher("/api/**")
                .authorizeRequests()
                // 所有以 /api 開頭的請(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:\":\"您無權(quá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:\":\"您無權(quán)訪問02\"}");
                    })
                    .and()
                // 用戶認(rèn)證
                .addFilterBefore((request, response, chain) -> {
                    // 此處可以模擬從 token 中解析出用戶名、權(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
 */
@Configuration
public class WebSiteSecurityFilterChainConfig {
    /**
     * 處理 給 webSite(非前后端分離) 端使用的過濾鏈
     * 以 頁面 的格式返回給前端
     */
    @Bean
    @Order(2)
    public SecurityFilterChain webSiteSecurityFilterChain(HttpSecurity http) throws Exception {

        AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);

        // 創(chuàng)建用戶
        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());

        // 只處理 所有 開頭的請(qǐng)求
        return http.antMatcher("/**")
                .authorizeRequests()
                // 所有請(qǐng)求都必須要認(rèn)證才可以訪問
                    .anyRequest()
                    .hasRole("ADMIN")
                    .and()
                // 禁用csrf
                .csrf()
                    .disable()
                // 啟用表單登錄
                .formLogin()
                    .permitAll()
                    .and()
                // 捕獲成功認(rèn)證后無權(quá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、控制器寫法

/**
 * 資源控制器
 *
 * @author huan.fu 2021/7/13 - 下午9:33
 */
@Controller
public class ResourceController {

    /**
     * 返回用戶信息
     */
    @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)限訪問 api

app 有權(quán)限訪問 api

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

app 無權(quán)限訪問 api

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

admin 用戶有權(quán)限訪問 網(wǎng)站 api

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

dev 用戶無權(quán)限訪問 網(wǎng)站 api

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

六、完整代碼

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

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

相關(guān)文章

  • Java中加鎖的方式代碼示例

    Java中加鎖的方式代碼示例

    這篇文章主要給大家介紹了關(guān)于Java中加鎖方式的相關(guān)資料,我們平時(shí)開發(fā)的過程中難免遇到多線程操作共享資源的時(shí)候,這時(shí)候一般可以通過加鎖的方式保證操作的安全性,需要的朋友可以參考下
    2023-09-09
  • java+mysql實(shí)現(xiàn)圖書館管理系統(tǒng)實(shí)戰(zhàn)

    java+mysql實(shí)現(xiàn)圖書館管理系統(tǒng)實(shí)戰(zhàn)

    這篇文章主要為大家詳細(xì)介紹了java+mysql實(shí)現(xiàn)圖書館管理系統(tǒng)實(shí)戰(zhàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • maven配置本地倉庫的方法步驟

    maven配置本地倉庫的方法步驟

    本文主要介紹了maven配置本地倉庫的方法步驟,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • java讀取XML文件的四種方法總結(jié)(必看篇)

    java讀取XML文件的四種方法總結(jié)(必看篇)

    下面小編就為大家?guī)硪黄猨ava讀取XML文件的四種方法總結(jié)(必看篇)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-06-06
  • Spring使用注解進(jìn)行對(duì)象注入的示例詳解

    Spring使用注解進(jìn)行對(duì)象注入的示例詳解

    獲取?Bean?對(duì)象也叫做對(duì)象裝配,就是把對(duì)象取出來放到某個(gè)類中,有時(shí)候也叫對(duì)象注入,常見有關(guān)對(duì)象注入的注解有兩個(gè),一個(gè)是@Autowired,另外一個(gè)是@Resource,下面就來講講它們的具體使用吧
    2023-07-07
  • mybatis的if判斷不要使用boolean值的說明

    mybatis的if判斷不要使用boolean值的說明

    這篇文章主要介紹了mybatis的if判斷不要使用boolean值的說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • Spring?bean配置單例或多例模式方式

    Spring?bean配置單例或多例模式方式

    這篇文章主要介紹了Spring?bean配置單例或多例模式方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • 簡(jiǎn)單談?wù)凧ava類與類之間的關(guān)系

    簡(jiǎn)單談?wù)凧ava類與類之間的關(guān)系

    類與類之間的關(guān)系對(duì)于理解面向?qū)ο缶哂泻苤匾淖饔茫郧霸诿嬖嚨臅r(shí)候也經(jīng)常被問到這個(gè)問題,在這里我就簡(jiǎn)單給大家介紹一下。
    2016-05-05
  • Java數(shù)據(jù)結(jié)構(gòu)與算法學(xué)習(xí)之雙向鏈表

    Java數(shù)據(jù)結(jié)構(gòu)與算法學(xué)習(xí)之雙向鏈表

    雙向鏈表也叫雙鏈表,是鏈表的一種,它的每個(gè)數(shù)據(jù)結(jié)點(diǎn)中都有兩個(gè)指針,分別指向直接后繼和直接前驅(qū)。所以,從雙向鏈表中的任意一個(gè)結(jié)點(diǎn)開始,都可以很方便地訪問它的前驅(qū)結(jié)點(diǎn)和后繼結(jié)點(diǎn)。本文將為大家詳細(xì)介紹雙向鏈表的特點(diǎn)與使用,需要的可以參考一下
    2021-12-12
  • 淺談Java代理(jdk靜態(tài)代理、動(dòng)態(tài)代理和cglib動(dòng)態(tài)代理)

    淺談Java代理(jdk靜態(tài)代理、動(dòng)態(tài)代理和cglib動(dòng)態(tài)代理)

    下面小編就為大家?guī)硪黄獪\談Java代理(jdk靜態(tài)代理、動(dòng)態(tài)代理和cglib動(dòng)態(tài)代理)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-01-01

最新評(píng)論

梁平县| 平昌县| 龙门县| 临高县| 赫章县| 凤阳县| 隆回县| 博白县| 秭归县| 梧州市| 蒙城县| 江津市| 罗城| 克东县| 东至县| 揭西县| 和政县| 平山县| 枝江市| 绵竹市| 南召县| 博乐市| 丹寨县| 林周县| 铅山县| 佛学| 深州市| 颍上县| 隆林| 龙川县| 通辽市| 乌苏市| 政和县| 靖江市| 洛隆县| 电白县| 兰考县| 巴彦县| 方正县| 汝南县| 翼城县|