우리는 이미 논의했습니다. OAuth 2.0 인증을 구성하는 방법 그리고 사용자 지정 토큰 저장소를 구축하는 방법. 이 시리즈의 마지막 글에서는 다음을 사용하여 사용자 지정 동적 클라이언트 등록을 구현하는 방법에 대해 알아봅니다. 스프링 보안 인증 2. 다음을 읽어 보시기 바랍니다. 1부 그리고 파트 2 먼저, 중단한 부분부터 계속 진행하겠습니다.
클라이언트 데이터 저장을 담당하는 엔티티를 만드는 것부터 시작하겠습니다:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
가져오기 com.카우치베이스.클라이언트.자바.저장소.주석.Id; 가져오기 롬복.데이터; 가져오기 롬복.NoArgsConstructor; 가져오기 org.스프링 프레임워크.데이터.카우치베이스.핵심.매핑.문서; 가져오기 javax.유효성 검사.제약 조건.NotNull; 가져오기 자바.활용.*; @NoArgsConstructor @Data 문서 public 클래스 사용자 지정 클라이언트 세부 정보 확장 기본 엔티티 { @Id @NotNull 비공개 문자열 id; @NotNull 비공개 문자열 clientId; 비공개 문자열 클라이언트 비밀; 비공개 설정<String> resourceIds = new 해시셋<>(); 비공개 부울 비밀필수; 비공개 부울 범위; 비공개 설정<String> 범위 = new 해시셋<>(); 비공개 설정<String> 승인된 그랜트 유형 = new 해시셋<>(); 비공개 설정<String> 등록된 리디렉션우리 = new 해시셋<>(); 비공개 컬렉션<String> 당국 = new 해시셋<>(); 비공개 정수 액세스 토큰 유효 기간 초; 비공개 정수 새로고침토큰유효기간초; 비공개 부울 자동 승인; 비공개 지도<문자열, 개체> 추가정보 = new 해시맵<>(); } |
각 리포지토리는 다음과 같습니다:
|
1 2 3 4 5 6 7 8 9 10 11 |
가져오기 org.스프링 프레임워크.데이터.카우치베이스.핵심.쿼리.N1qlPrimaryIndexed; 가져오기 org.스프링 프레임워크.데이터.카우치베이스.핵심.쿼리.인덱싱된 보기; 가져오기 org.스프링 프레임워크.데이터.카우치베이스.저장소.카우치베이스 페이징 및 정렬 저장소; @N1qlPrimaryIndexed @인덱싱된 보기(디자인 문서 = "customClientDetails") public 인터페이스 사용자 지정 클라이언트 세부 정보 저장소 확장 카우치베이스 페이징 및 정렬 저장소<사용자 지정 클라이언트 세부 정보, 문자열> { 사용자 지정 클라이언트 세부 정보 findByClientId(문자열 clientId); } |
이제 우리는 클라이언트 세부 정보 서비스 인터페이스를 사용할 수 있습니다:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
가져오기 org.스프링 프레임워크.콩.공장.주석.자동 유선; 가져오기 org.스프링 프레임워크.보안.oauth2.공급자.클라이언트 세부 정보; 가져오기 org.스프링 프레임워크.보안.oauth2.공급자.클라이언트 세부 정보 서비스; 가져오기 org.스프링 프레임워크.보안.oauth2.공급자.클라이언트 등록 예외; 가져오기 org.스프링 프레임워크.보안.oauth2.공급자.클라이언트.BaseClientDetails; 가져오기 org.스프링 프레임워크.고정관념.서비스; 가져오기 자바.활용.스트림.수집가; @서비스 public 클래스 카우치베이스클라이언트디테일서비스 구현 클라이언트 세부 정보 서비스 { @자동 유선 비공개 사용자 지정 클라이언트 세부 정보 저장소 사용자 지정 클라이언트 세부 정보 저장소; @오버라이드 public 클라이언트 세부 정보 로드클라이언트별클라이언트아이디(문자열 clientId) 던지기 클라이언트 등록 예외 { 사용자 지정 클라이언트 세부 정보 클라이언트 = 사용자 지정 클라이언트 세부 정보 저장소.findByClientId(clientId); 문자열 resourceIds = 클라이언트.getResourceIds().스트림().수집(수집가.가입(",")); 문자열 범위 = 클라이언트.getScope().스트림().수집(수집가.가입(",")); 문자열 grantTypes = 클라이언트.승인된 그랜트 유형 가져오기().스트림().수집(수집가.가입(",")); 문자열 당국 = 클라이언트.getAuthorities().스트림().수집(수집가.가입(",")); BaseClientDetails base = new BaseClientDetails(클라이언트.getClientId(), resourceIds, 범위, grantTypes, 당국); base.설정 클라이언트 비밀(클라이언트.getClientSecret()); base.설정 액세스 토큰 유효성 초(클라이언트.getAccessTokenValiditySeconds()); base.설정 새로 고침 토큰 유효 기간 초(클라이언트.getRefreshTokenValiditySeconds()); base.설정 추가 정보(클라이언트.getAdditionalInformation()); base.자동 승인 범위 설정(클라이언트.getScope()); 반환 base; } } |
저는 BaseClientDetails 클래스를 구현하는 대신 클라이언트 세부 정보 인터페이스를 사용합니다. 표준 JDBC 구현에서도 이 인터페이스를 사용하기 때문에 이것이 최선의 선택인 것 같습니다.
마지막으로, 우리는 AuthorizationServerConfig 를 사용하려면 CouchbaseClientDetailsService:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@Configuration 인증 서버 활성화 public 클래스 AuthorizationServerConfig 확장 권한부여서버구성자 어댑터 { 오토와이어드 비공개 카우치베이스클라이언트디테일서비스 카우치베이스클라이언트디테일서비스; 오버라이드 public void 구성(클라이언트 세부 정보 서비스 구성자 구성자) 던지기 예외 { 구성자.withClientDetails(카우치베이스클라이언트디테일서비스); } } |
전체 수업의 모습은 다음과 같습니다:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
가져오기 org.스프링 프레임워크.콩.공장.주석.자동 유선; 가져오기 org.스프링 프레임워크.컨텍스트.주석.구성; 가져오기 org.스프링 프레임워크.보안.인증.인증 관리자; 가져오기 org.스프링 프레임워크.보안.암호화.비밀번호.비밀번호 인코더; 가져오기 org.스프링 프레임워크.보안.oauth2.구성.주석.구성자.클라이언트 세부 정보 서비스 구성자; 가져오기 org.스프링 프레임워크.보안.oauth2.구성.주석.웹.구성.권한부여서버구성자 어댑터; 가져오기 org.스프링 프레임워크.보안.oauth2.구성.주석.웹.구성.EnableAuthorizationServer; 가져오기 org.스프링 프레임워크.보안.oauth2.구성.주석.웹.구성자.권한 부여 서버 엔드포인트 구성자; 가져오기 org.스프링 프레임워크.보안.oauth2.구성.주석.웹.구성자.권한 부여 서버 보안 구성자; 가져오기 org.스프링 프레임워크.보안.oauth2.공급자.토큰.토큰스토어; @Configuration 인증 서버 활성화 public 클래스 AuthorizationServerConfig 확장 권한부여서버구성자 어댑터 { 오토와이어드 비공개 토큰스토어 토큰 저장소; 오토와이어드 비공개 인증 관리자 인증 관리자; 오토와이어드 비공개 카우치베이스클라이언트디테일서비스 카우치베이스클라이언트디테일서비스; 오토와이어드 비공개 비밀번호 인코더 암호인코더; 오버라이드 public void 구성(클라이언트 세부 정보 서비스 구성자 구성자) 던지기 예외 { 구성자.withClientDetails(카우치베이스클라이언트디테일서비스); } 오버라이드 public void 구성(권한 부여 서버 엔드포인트 구성자 엔드포인트) 던지기 예외 { 엔드포인트.토큰 저장소(토큰 저장소) .인증 관리자(인증 관리자); } 오버라이드 public void 구성( 권한 부여 서버 보안 구성자 oauthServer) 던지기 예외 { oauthServer .토큰 키 액세스("permitAll()") .토큰 액세스 확인("isAuthenticated()"); } } |
이제 데이터베이스에 새 클라이언트를 삽입하고 이러한 자격 증명을 사용하여 OAuth를 통해 인증할 수 있습니다:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
정적 final 문자열 부여_유형_비밀번호 = "비밀번호"; 정적 final 문자열 권한 부여 코드 = "authorization_code"; 정적 final 문자열 REFRESH_TOKEN = "refresh_token"; 정적 final 문자열 IMPLICIT = "암시적"; 정적 final 문자열 SCOPE_READ = "read"; 정적 final 문자열 SCOPE_WRITE = "쓰기"; 정적 final 문자열 신뢰 = "신뢰"; 비공개 void createOauthClients() { 사용자 지정 클라이언트 세부 정보 클라이언트 = new 사용자 지정 클라이언트 세부 정보(); 클라이언트.setId("someId"); 클라이언트.setResourceIds(new 해시셋<>(배열.asList("resource_id")) ); 클라이언트.setClientId("android-client"); 클라이언트.설정 클라이언트 비밀("안드로이드-시크릿"); 클라이언트.권한 부여 유형 설정(new 해시셋<>(배열.asList(부여_유형_비밀번호, 권한 부여 코드, REFRESH_TOKEN, IMPLICIT))); 클라이언트.setScope(new 해시셋<>(배열.asList(SCOPE_READ, SCOPE_WRITE, 신뢰))); 클라이언트.setSecretRequired(true); 클라이언트.설정 액세스 토큰 유효성 초(50000); 클라이언트.설정 새로 고침 토큰 유효 기간 초(50000); 클라이언트.setScoped(false); 사용자 지정 클라이언트 세부 정보 저장소.저장(클라이언트); } |
TL;DR - 비결은 org.springframework.security.oauth2.provider.ClientDetailsService 인터페이스에 매개변수로 전달하여 클라이언트 세부 정보 서비스 구성자:
|
1 2 3 4 |
오버라이드 public void 구성(클라이언트 세부 정보 서비스 구성자 구성자) 던지기 예외 { 구성자.withClientDetails(카우치베이스클라이언트디테일서비스); } |
궁금한 점이 있으면 다음 주소로 트윗해 주세요. @deniswsrosa