Spring Security 다 중 필터 체인 사용 상세 설명

배경
우리 의 실제 개발 과정 에서 어떤 경우 에 이런 상황 이 존재 할 수 있 습 니 다.어떤 api,예 를 들 어 /api/** 은 App 단 에 사용 되 고 데이터 의 반환 은 모두 JSON 형식 으로 되 돌아 가 며 이런 API 의 인증 방식 은 모두 사용 하 는 TOKEN 으로 인증 합 니 다.한편, /api/** 이 API 를 제외 하고 모두 웹 페이지 에 사 용 된 것 으로 폼 인증 을 사용 하여 전단 에 되 돌려 주어 야 한다.
모두 어느 페이지 입 니 다.
수요
1.클 라 이언 트 에 게 사용 하 는 api
  • 모든 요청 을 차단 합 니 다.
  • /api/** 의 모든 요청 은 /api/** 의 캐릭터 가 필요 합 니 다.
  • 은 요청 헤더 에서 ROLE_ADMIN 을 얻 고 token 의 값 을 얻 으 면 인증 에 성공 했다 고 생각 하고 token 을 캐릭터 에 부여 한다.
  • 권한 이 없 으 면 JSON 대상 ROLE_ADMIN
  • 으로 전단 을 되 돌려 줍 니 다.
  • 방문 {message:" "} 터미널
  • 요청 헤드 는 /api/userInfo 을 가지 고 방문 할 수 있 습 니 다.
  • 요청 헤드 는 token 을 휴대 하지 않 고 접근 할 수 없습니다.
  • 2.사이트 에 사용 하 는 api
  • 에서 token 으로 시작 하 는 요청 을 차단 합 니 다.
  • 모든 요청 은 , /api/** 의 권한 이 필요 합 니 다.
  • 권한 이 없습니다.폼 으로 로그 인 해 야 합 니 다.
  • 로그 인 에 성공 한 후 권한 이 없 는 요청 에 방문 하여 바 이 두 로 바로 이동 합 니 다.
  • 2 개 내장 사용자 구축
  • 사용자 1:admin/admin 보유 ROLEADMIN 캐릭터
  • 사용자 2:dev/dev 보유 ROLEDEV 캐릭터
  • 방문 ROLE_ADMIN 터미널
  • /index 사용자 가 방문 하여 방문 할 수 있 습 니 다.
  • admin 사용자 가 방문 할 수 없고 접근 할 수 없 으 며 권한 이 부족 합 니 다.
  • 3.실현 방안
    프로젝트 1:
    여러 서비스 로 직접 뜯 었 는데 그 중에서 dev 은 하나의 서비스 가 되 었 다./api/** 의 분 리 는 다른 서비스 로 되 어 있다.각 서 비 스 는 자신의 설정 을 사용 하여 서로 영향 을 주지 않 습 니 다.
    방안 2
    같은 서비스 에서 작성 합 니 다.서로 다른 요 구 는 서로 다른 /api/** 을 사용 하여 이 루어 진다.
    고려 를 통 해 여 기 는 SecurityFilterChain 을 사용 하여 이 루어 집 니 다.방안 이 간단 하고 사용 방안 이 실현 되 기 때문에 같은 항목 에서 여러 개의 필터 체인 을 사용 하 는 것 을 기록 할 수 있 습 니 다.모든 때 가 아니 라 여러 항목 으로 나 눌 수 있 기 때 문 입 니 다.
    확장:
    1.Spring Security 의 구조
    SecurityFilterChain的结构
    2.SecurityFilterChain 의 집행 순 서 를 제어 한다.SecurityFilterChain 주 해 를 사용 합 니 다.
    3.그 org.springframework.core.annotation.Order 을 어떻게 선택 하 는 지 살 펴 봅 니 다.SecurityFilterChain 방법 보기
    실현
    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           
         */
        @Bean
        @Order(1)
        public SecurityFilterChain appSecurityFilterChain(HttpSecurity http) throws Exception {
            //     /api      
            return http.antMatcher("/api/**")
                    .authorizeRequests()
                    //     /api          ADMIN    
                        .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:\":\"     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:\":\"     02\"}");
                        })
                        .and()
                    //     
                    .addFilterBefore((request, response, chain) -> {
                        //         token        、   
                        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.사이트 엔 드 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;
    
    /**
     *             
     *
     * @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);
    
            //     
            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());
    
            //             
            return http.antMatcher("/**")
                    .authorizeRequests()
                    //                
                        .anyRequest()
                        .hasRole("ADMIN")
                        .and()
                    //   csrf
                    .csrf()
                        .disable()
                    //       
                    .formLogin()
                        .permitAll()
                        .and()
                    //               ,        
                    .exceptionHandling()
                        .accessDeniedHandler((request, response, exception) -> {
                            response.sendRedirect("http://www.baidu.com");
                        })
                        .and()
                    .build();
        }
    
        /**
         *       
         */
        @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>
    
    5.실현 효과
    1.app 은 api 에 접근 할 수 있 는 권한 이 있 습 니 다.
    app 有权限访问 api
    2.app 접근 권한 없 음 api
    app 无权限访问 api
    3.admin 사용자 가 사이트 api 를 방문 할 수 있 는 권한 이 있 습 니 다.
    admin 用户有权限访问 网站 api
    4.dev 사용자 가 사이트 api 에 접근 할 수 있 는 권한 이 없습니다.
    dev 用户无权限访问 网站 api
    권한 이 없 는 API 를 방문 하여 바 이 두 첫 페이지 로 바로 이동 합 니 다.
    6.전체 코드
    https://gitee.com/huan1993/Spring-Security/tree/master/multi-security-filter-chain
    스프링 시 큐 리 티 다 중 필터 링 체인 의 사용 에 대한 상세 한 설명 은 여기까지 입 니 다.스프링 시 큐 리 티 다 중 필터 링 체인 에 관 한 내용 은 예전 의 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 부탁드립니다!

    좋은 웹페이지 즐겨찾기