以下のカスタムUserDetailsService
を このSpring OAuth2サンプル に追加するにはどうすればよいですか?
デフォルトのuser
とデフォルトのpassword
は、authserver
アプリの application.properties
ファイルで定義されています。
ただし、テスト目的で、次のカスタムUserDetailsService
を demo
アプリのauthserver
パッケージ に追加したいと思います。
package demo;
import Java.util.List;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.provisioning.UserDetailsManager;
import org.springframework.stereotype.Service;
@Service
class Users implements UserDetailsManager {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
String password;
List<GrantedAuthority> auth = AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER");
if (username.equals("Samwise")) {
auth = AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_HOBBIT");
password = "TheShire";
}
else if (username.equals("Frodo")){
auth = AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_HOBBIT");
password = "MyRing";
}
else{throw new UsernameNotFoundException("Username was not found. ");}
return new org.springframework.security.core.userdetails.User(username, password, auth);
}
@Override
public void createUser(UserDetails user) {// TODO Auto-generated method stub
}
@Override
public void updateUser(UserDetails user) {// TODO Auto-generated method stub
}
@Override
public void deleteUser(String username) {// TODO Auto-generated method stub
}
@Override
public void changePassword(String oldPassword, String newPassword) {
// TODO Auto-generated method stub
}
@Override
public boolean userExists(String username) {
// TODO Auto-generated method stub
return false;
}
}
ご覧のとおり、このUserDetailsService
はまだautowired
ではなく、テスト目的でのみ設計されているため、意図的に安全でないパスワードを使用しています。
ユーザーがusername=Samwise
でpassword=TheShire
として、またはusername=Frodo
でpassword=MyRing
としてログインできるように、 GitHubサンプルアプリ にどのような特定の変更を加える必要がありますか?AuthserverApplication.Java
または他の場所に変更を加える必要がありますか?
提案:
Spring OAuth2開発者ガイド は、GlobalAuthenticationManagerConfigurer
を使用してUserDetailsService
をグローバルに構成するように指示しています。ただし、これらの名前をグーグルで検索しても、役立つ結果は得られません。
また、内部スプリングセキュリティを使用する別のアプリINSTEAD OF OAuthは次の構文を使用してUserDetailsService
を接続しますが、構文を現在の構文に調整する方法がわかりませんOP:
@Order(Ordered.HIGHEST_PRECEDENCE)
@Configuration
protected static class AuthenticationSecurity extends GlobalAuthenticationConfigurerAdapter {
@Autowired
private Users users;
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(users);
}
}
次のように、@Autowire
内でOAuth2AuthorizationConfig
を使用して、Users
をAuthorizationServerEndpointsConfigurer
に接続してみました。
@Autowired//THIS IS A TEST
private Users users;//THIS IS A TEST
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager)
.accessTokenConverter(jwtAccessTokenConverter())
.userDetailsService(users)//DetailsService)//THIS LINE IS A TEST
;
}
ただし、Spring Bootログは、ユーザーSamwise
が見つからなかったことを示しています。これは、UserDetailsService
が正常に接続されなかったことを意味します。 SpringBootログからの関連する抜粋は次のとおりです。
2016-04-20 15:34:39.998 DEBUG 5535 --- [nio-9999-exec-9] o.s.s.a.dao.DaoAuthenticationProvider :
User 'Samwise' not found
2016-04-20 15:34:39.998 DEBUG 5535 --- [nio-9999-exec-9]
w.a.UsernamePasswordAuthenticationFilter :
Authentication request failed:
org.springframework.security.authentication.BadCredentialsException:
Bad credentials
他に何を試すことができますか?
SpringSecurityを使用してoauthサーバーを開発するときに、同様の問題が発生しました。更新トークンを認証するためにUserDetailsService
を追加したかったので、状況は少し異なりましたが、私の解決策はあなたにも役立ちます。
あなたと同じように、私は最初にUserDetailsService
を使用してAuthorizationServerEndpointsConfigurer
を指定しようとしましたが、これは機能しません。これがバグなのか設計によるものなのかはわかりませんが、さまざまなoauth2クラスがそれを見つけるには、UserDetailsService
をAuthenticationManager
に設定する必要があります。これは私のために働いた:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
Users userDetailsService;
@Autowired
public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
// other stuff to configure your security
}
}
73行目から次のように変更した場合は、うまくいくと思います。
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.parentAuthenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
もちろん、WebSecurityConfigurerAdapter
のどこかに@Autowired Users userDetailsService;
を追加する必要もあります。
私が言及したかった他のこと:
GlobalAuthenticationManagerConfigurer
はほぼ間違いなくタイプミスであり、Springのソースコードのどこにもその文字列が見つかりません。私は同じ問題に遭遇し、元々はMananMehtaが投稿したのと同じ解決策を持っていました。つい最近、SpringSecurityとSpringoauth2のバージョンの組み合わせにより、トークンを更新しようとすると、HTTP500エラーが発生してUserDetailsService is required
私のログ。
関連するスタックトレースは次のようになります。
Java.lang.IllegalStateException: UserDetailsService is required.
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$UserDetailsServiceDelegator.loadUserByUsername(WebSecurityConfigurerAdapter.Java:463)
at org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper.loadUserDetails(UserDetailsByNameServiceWrapper.Java:68)
at org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider.authenticate(PreAuthenticatedAuthenticationProvider.Java:103)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.Java:174)
at org.springframework.security.oauth2.provider.token.DefaultTokenServices.refreshAccessToken(DefaultTokenServices.Java:150)
下部に、DefaultTokenServices
がトークンを更新しようとしていることがわかります。次に、AuthenticationManager
を呼び出して再認証します(ユーザーがアクセス許可を取り消した場合やユーザーが削除された場合など)が、ここですべてが解明されます。スタックトレースの一番上に、私の美しいUserDetailsServiceDelegator
ではなくloadUserByUsername
がUserDetailsService
への呼び出しを取得していることがわかります。 WebSecurityConfigurerAdapter
の中にUserDetailsService
を設定しましたが、他に2つのWebSecurityConfigurerAdapter
があります。 1つはResourceServerConfiguration
用、もう1つはAuthorizationServerSecurityConfiguration
用であり、これらの構成では、設定したUserDetailsService
を取得できません。
Spring Securityをトレースして、何が起こっているのかをつなぎ合わせると、「ローカル」AuthenticationManagerBuilder
と「グローバル」AuthenticationManagerBuilder
があり、それをに設定する必要があることがわかりました。この情報をこれらの他のビルダーコンテキストに渡すためのグローバルバージョン。
したがって、私が思いついた解決策は、他のコンテキストがグローバルバージョンを取得するのと同じ方法で「グローバル」バージョンを取得することでした。 WebSecurityConfigurerAdapter
の中には、次のものがありました。
@Autowired
public void setApplicationContext(ApplicationContext context) {
super.setApplicationContext(context);
AuthenticationManagerBuilder globalAuthBuilder = context
.getBean(AuthenticationManagerBuilder.class);
try {
globalAuthBuilder.userDetailsService(userDetailsService);
} catch (Exception e) {
e.printStackTrace();
}
}
そして、これはうまくいきました。他のコンテキストには私のUserDetailsService
がありました。将来この地雷原に出くわす勇敢な兵士のために、これをここに残しておきます。
私の要件は、oauth2電子メール属性の後ろからデータベースオブジェクトを取得することでした。カスタムユーザー詳細サービスを作成する必要があると思ったので、この質問を見つけました。実際、OidcUserインターフェイスを実装して、そのプロセスにフックする必要があります。
最初はOAuth2UserServiceだと思っていましたが、オープンID接続になるようにAWSCognito認証プロバイダーを設定しました。
//inside WebSecurityConfigurerAdapter
http
.oauth2Login()
.userInfoEndpoint()
.oidcUserService(new CustomOidcUserServiceImpl());
...
public class CustomOidcUserServiceImpl implements OAuth2UserService<OidcUserRequest, OidcUser> {
private OidcUserService oidcUserService = new OidcUserService();
@Override
public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException {
OidcUser oidcUser = oidcUserService.loadUser(userRequest);
return new CustomUserPrincipal(oidcUser);
}
}
...
public class CustomUserPrincipal implements OidcUser {
private OidcUser oidcUser;
//forward all calls onto the included oidcUser
}
カスタムサービスは、特注のロジックを使用できる場所です。 UserDetails
にCustomUserPrincipal
インターフェースを実装して、自動UIテストを容易にするためにライブとテストに異なる認証メカニズムを使用できるようにする予定です。
誰のためにUserDetailsService is required
リフレッシュトークンの実行中にエラーが発生し、すでにUserDetailsService
Beanがあることを確認しました。
これを追加してみてください:
@Configuration
public class GlobalSecurityConfig extends GlobalAuthenticationConfigurerAdapter {
private UserDetailsService userDetailsService;
public GlobalSecurityConfig(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
}
これは私の試行錯誤であり、おそらくあなたにとってはうまくいきません。
ちなみに、春までにBeanが選択する「推測」をあきらめると、AuthorizationServerConfigurerAdapter
とWebSecurityConfigurerAdapter
を拡張して、すべてを自分で構成できますが、春の自動構成の能力が失われると思います。いくつかの構成をカスタマイズする必要があるのに、なぜすべてを構成する必要があるのですか?