원래 문서를 읽어 봄 보안 소스에 대해 쓰고 싶었지만, 시간의 문제는 다른 한편으로는, 실제적인 목적을 위해, 관련로드 프로세스에서 녹음을 시작하는이 가고, 한 손을 고려, 인증 및 권한 부여 프로세스를 요청합니다.
다음과 같이 요약 :
1. 프로세스 개요
2, 토큰 획득 프로세스 분석
3 요청한 인증 및 승인 프로세스 분석
첫째, 프로세스 개요를 시작합니다
부팅 과정의 주요 초점은 포함 로딩 구성 정보 및 필터 체인을 구축 .
스프링 보안 프레임 워크는 필터 체인의 핵심! 염려되는 분석 과정의 시작과 끝 디버깅 코드의 초점이다.
첫번째 관점 입구 org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration 클래스, 메소드 setFilterChainProxySecurityConfigurer 거기
대 (SecurityConfigurer <필터 WebSecurity> webSecurityConfigurer : webSecurityConfigurers) { webSecurity.apply (webSecurityConfigurer); }
구성 (보안 관련), org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter 유형 구성 (서버 자원) 유형을 org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter합니다 org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter 형 구성 (연관된 권한 서버) org.springframework.security.config.annotation.web.builders.WebSecurity 객체에 부착되어있다.
지켜봐 방법 springSecurityFilterChain을 ,
1 공용 필터 springSecurityFilterChain ()는 슬로우 예외 { 2 부울 hasConfigurers 용의 webSecurityConfigurers =! = null의 3 &&를! webSecurityConfigurers.isEmpty (); (4) 만약 (! hasConfigurers) { 5 WebSecurityConfigurerAdapter 어댑터 = objectObjectPostProcessor 6 .postProcess ( 새로운 WebSecurityConfigurerAdapter () { 7 }); 8 webSecurity.apply (어댑터); 9 } 10 반환webSecurity.build (); 11 }
라인 10에 후속 org.springframework.security.config.annotation.AbstractSecurityBuilder # 빌드를 입력,
1 공용 최종 O 빌드 () 가 발생 예외 { 2 경우 ( 이 .building.compareAndSet ( 거짓 , 참 )) { 3 이 .object = doBuild (); 4 리턴 이 .object 단계; 5 } 6 던져 새로운 AlreadyBuiltException ( "이 개체는 이미 구축 된" ); 7 }
, doBuild () 메소드에 계속
1 보호 최종 O의 doBuild ()는 슬로우 예외 { 2 동기화 (하는 configurer) { 3 buildState = BuildState.INITIALIZING 단계; 4 5 beforeInit (); 6 초기화 (); 7 8 buildState = BuildState.CONFIGURING; 9 10 beforeConfigure (); 11 구성 (); 12 13 buildState = BuildState.BUILDING; 14 15 O 결과 = performBuild (); (16) 17 buildState = BuildState.BUILT; 18 19 복귀 결과; 20 } 21 }
봄 보안 구성은 일반적으로 org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter을 상속 때문에, 여기를보세요. 6 호선의 init (), 라인 (11) 구성 (), 라인 (15) performBuild 위의 키 ()를 참조하십시오. 초기화 () 메소드 org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter # 초기화 방법을 트리거
1 공용 공극 INIT ( 최종 WebSecurity 웹)은 슬로우 {예외 2 최종 HttpSecurity HTTP = getHttp (); 3 web.addSecurityFilterChainBuilder (HTTP) .postBuildAction ( 신규 의 Runnable () { 4 공용 무효 실행 () { 5 FilterSecurityInterceptor를 securityInterceptor = HTTP 6 .getSharedObject (FilterSecurityInterceptor가. 등급 ) 7 web.securityInterceptor (securityInterceptor) 8 } 9 }); 10 }
이어서 getHttp () 메소드는, 다음의 코드는 기본 필터 체인을 포함하는 구성된다 보면
1 HTTP 2 .csrf ().와 () 3 .addFilter ( 새로운 WebAsyncManagerIntegrationFilter ()) 4 .exceptionHandling ().와 () 5 .headers ().와 () 6 .sessionManagement ().와 () 7 .securityContext () .and () 8 .requestCache ().와 () 9 .anonymous ().와 () 10 .servletApi ().와 () 11 .apply ( 새로운 DefaultLoginPageConfigurer <> ()). 그리고 () 12 .로그 아웃();
아래와 같이 각 단계, 디버그로 구성된 필터에서 참조에 해당
마지막으로이 한편 getHttp () 메소드
1 개 구성 (HTTP)
여기서 구성 org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter 유형을 행한다 (보안 관련) org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter 타입 구성, (서버 자원) , org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter는 구성 방법의 많은 종류 (인증 서버 관련)을 구성합니다.
이것은 일반적으로 생성 및 로딩 기본 필터 체인 프로세스를 구성 정보를 설명합니다.
두 토큰 획득 프로세스 분석
사용자가 리소스에 대한 액세스를 요청하는 경우이 문서는 짧은 암호 인증 모드에서 OAuth2 (암호 부여 형)의 사용, 당신은 먼저 사용자를 인증 할 때 사용자 이름과 암호를 통과, 인증 서버 토큰을 반환, 나중에이 토큰을 사용하면 액세스 할 수 있습니다 그 특권 자원. 세부 사항 참조 : https://developer.okta.com/blog/2018/06/29/what-is-the-oauth2-password-grant를 .
따라서이 문서는 단일 로그온 프로세스의 토큰을 얻을 수 있습니다에 의미합니다.
토큰이 링크를 획득 : / OAuth를 / 토큰, 해당 코드 org.springframework.security.oauth2.provider.endpoint.TokenEndpoint # postAccessToken 스프링 보안 OAuth2를 항아리 패키지;
필터를 통한 전체 흐름 내용은 필터 즉, org.springframework.security.web.FilterChainProxy의 필터 체인을 수행하는 트랙을 깰 수 org.springframework.security.web.FilterChainProxy.VirtualFilterChain에 상기 방법에 #doFilter 브레이크 .
여기에 내가 주로이 중단 점은 바로 다음 코드 줄 때까지 postAccessToken 방법에 단계적으로 이동되면, 토큰 생성 알고 싶어요,
. OAuth2AccessToken 토큰 = getTokenGranter () 부여 (tokenRequest.getGrantType (), tokenRequest);
요청이 토큰이 부여되는 경우 여기에, 단계적으로는 방법 org.springframework.security.oauth2.provider.CompositeTokenGranter # 보조금에 마침내 내부로 침입,하고있다
1 공용 OAuth2AccessToken 그랜트 (문자열 grantType, TokenRequest tokenRequest) { 2 대 (승인 기 TokenGranter : tokenGranters) { 3 OAuth2AccessToken 부여 = granter.grant (grantType, tokenRequest); 4 경우 (부여 =! 널을 ) { 5 반환 승인을; 6 } 7 } 8 복귀 널 ; 9 }
이하에서도 tokenRequest,
말 그대로 참조 아마 다섯 OAuth2를 부여 유형의 해당 보조금 유형의 종류 참조 참조 https://oauth.net/2/grant-types/을 , 우리는 승인 기 암호 모드, 위의 마지막 그림을 메소드 org.springframework에 해당 세 번째 줄 다른 승인 기 .security.oauth2.provider.CompositeTokenGranter # 보조금을 직접 반환 null이 일치하지 않을 경우, 해당 부 여자를 선택하는 보조금 유형을 기반으로합니다. 이 방법은 아래의 최종 승인에 부 여자를 진행
보호 OAuth2AccessToken getAccessToken (ClientDetails 클라이언트는 TokenRequest tokenRequest) { 반환 tokenServices.createAccessToken (getOAuth2Authentication (클라이언트, tokenRequest을)); }
마지막으로 getOAuth2Authentication (클라이언트, tokenRequest)으로,이 방법은 다음과 같은 코드를 가지고,
userAuth = authenticationManager.authenticate (userAuth);
AuthenticationManager에 상기하는 org.springframework.security.authentication.ProviderManager입니다 몇 가지 org.springframework.security.authentication.AuthenticationProvider, 공급자 인증을 캡슐화하고 null이 아닌 인증 인증을 계속 완료 반환, 우리는 프로젝트에 사용 org.springframework입니다. security.authentication.dao.DaoAuthenticationProvider, 그녀는, 사용자 암호 검증 등 (예를 들어, 구성 파일 인 검사기) 검사의 모든 종류의 할 것;
接着 进入 org.springframework.security.oauth2.provider.token.DefaultTokenServices # createAccessToken (org.springframework.security.oauth2.provider.OAuth2Authentication) 方法,
1 @Transactional 2 공개 OAuth2AccessToken createAccessToken (OAuth2Authentication 인증) 발생 있는 AuthenticationException { 3 4 OAuth2AccessToken existingAccessToken = tokenStore.getAccessToken (인증); 5 OAuth2RefreshToken refreshToken = 널 ; (6) 의 경우 (existingAccessToken! = null의 ) { 7 경우 (existingAccessToken.isExpired ()) { 도 8 의 경우 (existingAccessToken.getRefreshToken ()! = null의 ) { 9 refreshToken =existingAccessToken.getRefreshToken (); 10 // 때 새로 고침 토큰을 제거 할 수 토큰 상점 (11) // 액세스 토큰을 제거하지만, 우리가 원하는 12 // 것은 ... 반드시 13 tokenStore.removeRefreshToken (refreshToken); 14 } 15 tokenStore.removeAccessToken (existingAccessToken); (16) } (17) 또 { 18 // 인증이 변경된 경우에, 액세스 토큰 재 저장 19 tokenStore.storeAccessToken (existingAccessToken, 인증); (20) 반환 existingAccessToken을; 21 } 22 } 23 24 // 기존 없었다 경우에만 새로운 새로 고침 토큰을 생성 (25) // 만료 된 액세스 토큰과 관련된. 26 // 클라이언트는 기존의 새로 고침 토큰을 보유 할 수있다, 그래서 우리는 그것을 다시 사용 27 // 경우 그 이전 액세스 토큰 (28) // 만료. 29 일 경우 (refreshToken == 널 ) { 30 refreshToken = createRefreshToken (인증); 31 } 32 //이 경우 그러나 새로 고침 토큰 자체는 다시 발행해야 할 수도 있습니다 (33) // 만료를. (34) 그 밖의 경우 (refreshToken instanceof를 ExpiringOAuth2RefreshToken) { 35 ExpiringOAuth2RefreshToken 만료 = (ExpiringOAuth2RefreshToken) refreshToken; 36 의 경우 (에 System.currentTimeMillis ()> expiring.getExpiration () 다음 getTime ().) { 37 refreshToken = createRefreshToken (인증); 38 } 39 } 40 41 OAuth2AccessToken accessToken =createAccessToken (인증 refreshToken); 42 tokenStore.storeAccessToken (accessToken 인증); 43 // 경우는 수정 된 44 refreshToken = accessToken.getRefreshToken (); 45 의 경우 (refreshToken =! 널 ) { 46 tokenStore.storeRefreshToken (refreshToken 인증); 47 } 48 반환 accessToken; 49 (50) }
우리의 프로젝트는 코드가 만료 refreshToken에 직접 뒤에 20 개 행을 반환, 만기 된 토큰이없는 경우, 레디 스 저장 토큰을 사용, 만료 갱신 과정 accessToken과 refreshToken 생성, 기본값은 UUID.randomUUID (). ToString입니다 ()는 시간이 메커니즘을 만료하고, 마지막으로 입금했다하는 UUID를 생성
tokenStore는 우리의 프로젝트에 대한 tokenStore은 레디 스입니다.
이 토큰 획득 프로세스 분석이 완료됩니다.
셋째, 인증 및 권한 부여 프로세스 분석을 요청
클라이언트 응용 프로그램이 아이를 요청할 때, 당신은 인증 서버 인증에 먼저 갈 필요, 인증 서버는 감지하고 기관에, 어떻게 할? 의는 B를 부르 자, 여기이 개 서비스 인증 및 권한 부여 중 하나에서 수행되는 서비스 응용 프로그램 A의 가정,
인증 및 권한 부여 프로세스 다이어그램은 다음과 같다,