스프링 부트 + Oauth2 클라이언트 자격 정보
Spring Boot 시 클라이언트 credentials 흐름과 함께 Ath2를 사용하여 마이크로 서비스를 보호하려고 합니다.
덧붙여서, 이러한 마이크로 서비스는 미들웨어 레이어에서만 서로 대화합니다.즉, 인증(Facebook으로서의 사용자 로그인 프로세스)을 허용하기 위해 사용자 자격 정보가 필요하지 않습니다.
이 통신을 관리하기 위한 인증 및 자원 서버를 작성하는 방법을 나타내는 샘플을 인터넷에서 찾았습니다.다만, 유저 credential(3개의 다리)을 사용해 조작하는 방법을 설명하는 예를 발견했습니다.
Spring Boot 및 Oauth2에서의 방법 샘플이 있습니까?사용하는 스코프에 대해 좀 더 자세히 알려주시면 토큰 교환을 해주시면 감사하겠습니다.
REST 서비스는 Oauth2 Client credentials 스킴으로 보호되고 있습니다.리소스와 권한 부여 서비스가 동일한 앱에서 실행 중이지만 다른 앱으로 분할할 수 있습니다.
@Configuration
public class SecurityConfig {
@Configuration
@EnableResourceServer
protected static class ResourceServer extends ResourceServerConfigurerAdapter {
// Identifies this resource server. Usefull if the AuthorisationServer authorises multiple Resource servers
private static final String RESOURCE_ID = "*****";
@Resource(name = "OAuth")
@Autowired
DataSource dataSource;
@Override
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests().anyRequest().authenticated();
// @formatter:on
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId(RESOURCE_ID);
resources.tokenStore(tokenStore());
}
@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
}
@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Resource(name = "OAuth")
@Autowired
DataSource dataSource;
@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore());
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.jdbc(dataSource);
}
}
}
Oauth2 테이블의 데이터 소스 설정:
@Bean(name = "OAuth")
@ConfigurationProperties(prefix="datasource.oauth")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
인증 및 자원 서버와의 통신 방법은 다음과 같습니다.
curl -H "Accept: application/json" user:password@localhost:8080/oauth/token -d grant_type=client_credentials
curl -H "Authorization: Bearer token" localhost:8080/...
Oauth2 데이터베이스에는 다음 레코드가 있습니다.
client_id resource_ids client_secret scope authorized_grant_types web_server_redirect_uri authorities access_token_validity refresh_token_validity additional_information autoapprove
user **** password NULL client_credentials NULL X NULL NULL NULL NULL
클라이언트 어플리케이션의 resttemplate
@Configuration
@EnableOAuth2Client
public class OAuthConfig {
@Value("${OAuth2ClientId}")
private String oAuth2ClientId;
@Value("${OAuth2ClientSecret}")
private String oAuth2ClientSecret;
@Value("${Oauth2AccesTokenUri}")
private String accessTokenUri;
@Bean
public RestTemplate oAuthRestTemplate() {
ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails();
resourceDetails.setId("1");
resourceDetails.setClientId(oAuth2ClientId);
resourceDetails.setClientSecret(oAuth2ClientSecret);
resourceDetails.setAccessTokenUri(accessTokenUri);
/*
When using @EnableOAuth2Client spring creates a OAuth2ClientContext for us:
"The OAuth2ClientContext is placed (for you) in session scope to keep the state for different users separate.
Without that you would have to manage the equivalent data structure yourself on the server,
mapping incoming requests to users, and associating each user with a separate instance of the OAuth2ClientContext."
(http://projects.spring.io/spring-security-oauth/docs/oauth2.html#client-configuration)
Internally the SessionScope works with a threadlocal to store variables, hence a new thread cannot access those.
Therefore we can not use @Async
Solution: create a new OAuth2ClientContext that has no scope.
*Note: this is only safe when using client_credentials as OAuth grant type!
*/
// OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, oauth2ClientContext);
OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, new DefaultOAuth2ClientContext());
return restTemplate;
}
}
restTemplate를 삽입하여 Oauth2 시큐어 서비스에 (비동기적으로) 대화할 수 있습니다.현재는 스코프를 사용하지 않습니다.
Spring-boot-2.7 및 Java 17로 업데이트합니다.
https://chuangtc.com/Java/spring-boot-27-security-social-login.php
public class SecurityConfig {
@Value("${spring.social.facebook.appSecret}")
String appSecret;
@Value("${spring.social.facebook.appId}")
String appId;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private FacebookConnectionSignup facebookConnectionSignup;
@Bean
public AuthenticationManager authManager(HttpSecurity http) throws Exception {
return http.getSharedObject(AuthenticationManagerBuilder.class)
.userDetailsService(userDetailsService)
.and()
.build();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.authorizeRequests()
.antMatchers("/login*", "/signin/**", "/signup/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout();
return http.build();
}
@Bean
// @Primary
public ProviderSignInController providerSignInController() {
ConnectionFactoryLocator connectionFactoryLocator = connectionFactoryLocator();
UsersConnectionRepository usersConnectionRepository = getUsersConnectionRepository(connectionFactoryLocator);
((InMemoryUsersConnectionRepository) usersConnectionRepository).setConnectionSignUp(facebookConnectionSignup);
return new ProviderSignInController(connectionFactoryLocator, usersConnectionRepository, new FacebookSignInAdapter());
}
private ConnectionFactoryLocator connectionFactoryLocator() {
ConnectionFactoryRegistry registry = new ConnectionFactoryRegistry();
registry.addConnectionFactory(new FacebookConnectionFactory(appId, appSecret));
return registry;
}
private UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
return new InMemoryUsersConnectionRepository(connectionFactoryLocator);
}
}
Facebook SignIn 어댑터
@Service
public class FacebookSignInAdapter implements SignInAdapter {
@Override
public String signIn(String localUserId, Connection<?> connection, NativeWebRequest request) {
System.out.println(" ====== Sign In adapter");
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(connection.getDisplayName(), null, Arrays.asList(new SimpleGrantedAuthority("FACEBOOK_USER"))));
return null;
}
}
언급URL : https://stackoverflow.com/questions/37534073/spring-boot-oauth2-client-credentials
'source' 카테고리의 다른 글
각도 순서 ng-반복 텍스트로 번호 정렬 (0) | 2023.02.25 |
---|---|
woocommerce의 카트 페이지에서 특정 제품 수량을 얻는 방법 (0) | 2023.02.25 |
"참이 아님"으로 부울 필드에 대한 쿼리(예: 거짓 또는 존재하지 않음) (0) | 2023.02.25 |
HTML 문자열을 JSON으로 쓰기 (0) | 2023.02.25 |
Angular에서 비활성화된 JavaScript를 처리하는 방법JS (0) | 2023.02.25 |