この記事に基づいて、Cookieを使用して(Androidクライアントアプリの)認証を実装しようとしています-http://automateddeveloper.blogspot.co.uk/2014/03/securing-your-mobile-api-spring-security.html
SecurityConfig:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final static String TOKEN_STRING = "my_token";
private final static String COOKIE_STRING = "my_cookie";
@Autowired
private UserDetailsService userSvc;
@Autowired
private MyTokenBasedRememberMeService tokenSvc;
@Autowired
private RememberMeAuthenticationProvider rememberMeProvider;
@Autowired
private MyAuthSuccessHandler authSuccess;
@Autowired
private MyAuthFailureHandler authFailure;
@Autowired
private MyLogoutSuccessHandler logoutSuccess;
@Autowired
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userSvc)
.passwordEncoder(passwordEncoder());
auth.authenticationProvider(rememberMeProvider);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/register").permitAll()
.anyRequest().authenticated().and()
.formLogin()
.loginPage("/")
.loginProcessingUrl("/loginendpoint")
.successHandler(authSuccess)
.failureHandler(authFailure).and()
.logout()
.logoutUrl("/logout")
.logoutSuccess(logoutSuccess)
.deleteCookies(COOKIE_STRING).and()
.rememberMe()
.rememberMeServices(tokenSvc).and()
.csrf()
.disable()
.addFilterBefore(rememberMeAuthenticationFilter(), BasicAuthenticationFilter.class)
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public RememberMeAuthenticationFilter rememberMeAuthenticationFilter() throws Exception {
return new RememberMeAuthenticationFilter(authenticationManager(), tokenBasedRememberMeService());
}
@Bean
public RememberMeAuthenticationProvider rememberMeAuthenticationProvider() {
return new RememberMeAuthenticationProvider(TOKEN_STRING);
}
@Bean
public MyTokenBasedRememberMeService tokenBasedRememberMeService() {
MyTokenBasedRememberMeService service = new MyTokenBasedRememberMeService(TOKEN_STRING,
userSvc);
service.setAlwaysRemember(true);
service.setCookieName(COOKIE_STRING);
return service;
}
@Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
}
MyTokenBasedRememberMeService:
public class MyTokenBasedRememberMeService extends TokenBasedRememberMeServices {
private final static String TOKEN_STRING = "my_token";
public MyTokenBasedRememberMeService(String key, UserDetailsService userDetailsService) {
super(key, userDetailsService);
}
@Override
protected String extractRememberMeCookie(HttpServletRequest request) {
String token = request.getHeader(TOKEN_STRING);
if ((token == null) || (token.length() == 0)) {
return "";
}
return token;
}
}
残念ながら、ログインに成功した後、クライアント側のCookieは空になります。
Set-Cookie: my_cookie=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/
どうしましたか?
-------編集1 -------
ブラウザに直接ログインした場合、Cookieは取得されません(たとえば、開発ツールで)?
postmanを使用してテストしたところ、JSESSIONID cookieのみを受け取りました(my_cookieは受け取りませんでした)。
また、カスタムログインコントローラーメソッドを使用していますか?(たとえば、ユーザーコントローラーはユーザーを明示的に認証していますか?)
はい、私はカスタムログインコントローラーメソッドを使用していますが、Spring Securityは初めてです。カスタムコントローラーなしで実行できる場合は、説明をいただければ幸いです。私のコントローラーはユーザーの認証を担当します。
認証を処理するためにスプリングセキュリティを使用していない場合は、Cookieなどを自分で明示的に設定する必要があると思われます
いいえ、スプリングセキュリティのみを使用しています。少なくとも私はそう思う ... :)
UserControllerログインメソッドは何をしていますか?
コードを更新しました。
-------編集2 -------
@rhindsのアドバイスと春のドキュメントによると、私はいくつかのことを修正しました(上記のコードが更新されています)。これでログインでき、ログインloginendpoint
後に取得できmy_cookie
ます。しかし、私は関連する質問があります:
同様のことをする人のために、私はこの素晴らしい記事も見ることをお勧めします-https://dzone.com/articles/secure-rest-services-using :)
さて、開始するのに最適な場所は、ログイン用のカスタムSpringコントローラーから離れて、Springセキュリティに委任することです-ドキュメントには、それを開始する方法のかなり良い概要が記載されています-開始するには、ここを参照してください
リンクされた記事から、構成コードを見ると:
@Override protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.authorizeRequests()
.antMatchers("/resources/**").permitAll()
.antMatchers("/sign-up").permitAll()
.antMatchers("/sign-in").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/")
.loginProcessingUrl("/loginprocess")
.failureUrl("/mobile/app/sign-in?loginFailure=true")
.permitAll().and()
.rememberMe().rememberMeServices(tokenBasedRememberMeService);
}
.formLogin()
呼び出しの下のセクションは、ログイン試行をリッスンPOST
するエンドポイント/loginprocess
をSpring-securityに指示しています-たとえば、この構成とエンドポイントがある場合、Spring-securityはそれをインターセプトし、認証マネージャーを使用して送信されたフォームを処理します(ユーザー名を期待)およびパスワードフィールドなど)。
次の重要な点は、あなたuserDetailsService
と認証管理者の配線です。
@Override protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsServiceImpl)
.passwordEncoder(bCryptPasswordEncoder());
auth.authenticationProvider(rememberMeAuthenticationProvider);
}
これにより、Spring-Securityは、提供されたログイン試行を前提としてユーザーオブジェクトのロードを試行する手段を提供します。クラスが実装されている限り、UserDetailsService
SpringSecurityには必要なものがすべて揃っているはずです。
すべてが正しいと仮定すると、カスタムログインコントローラーメソッドを削除し、を定義してloginProcessingUrl
からそれPOST
を定義すると、spring-securityが起動して(試行して)処理できるようになります。
spring-security configを機能させ、単純なログインケースを処理するのに少し時間を費やすだけの価値があるかもしれません。それがすべて、spring-security機械に委任されると、RememberMe側で構成を更新してワイヤリングする方が簡単になるはずです。
編集2への応答
ここでの一般的なアプローチに基づいて、リンクされた記事の実装の詳細に従っていることを前提としています:http://automateddeveloper.blogspot.co.uk/2014/03/securing-your-api-for-mobile-access.html(運用でリンクした実装の詳細の説明)
- ログインに成功すると、それに応じてCookieを受け取ります。さらにリクエストするには、トークンがサーバー側で自動的に追加される場合、手動でトークン(クライアント側)を追加する必要がありますか?
したがって、ログインしてからモバイルアプリからAPIリクエストを行うと仮定すると、記事のとおり、ユーザーがログインできるようにするには、アプリにWebビューが必要です。ユーザーがログインすると、WebViewはログインからの応答を受信します。クッキーを含めます。この時点で気になるのは、Cookieからトークンを抽出することだけです。その後は、Cookieは必要ありません。アプリでは、トークンを好きなように永続化でき、アプリから行うすべてのAPIリクエストでトークンを指定するように追加するだけです-記事のRememberMe実装は、APIリクエストヘッダーからトークンを抽出し、ユーザーを認証します。
- ログアウトはどうですか?「Spring」はどのユーザーがログアウトする必要があるかをどのように知るのでしょうか?
それはしません-設定はステートレスになるようにスプリングを設定しました、例えばそれはログインしたユーザーを追跡しません、それは有効なクッキーの存在によってログに記録されます(またはAPIリクエストの場合、トークンの存在抽出)-たとえば、ステートレスモードでは、アプリに対して行われたすべてのリクエストが、認証されているかどうかを確認するためにチェックされます
- トークンの有効期限はどうですか?デフォルトは2週間ですが、それではどうしますか?トークンが期限切れにならないように設定できますか?
繰り返しになりますが、上記のリンクで説明されているパターンに従っていると仮定すると、これは問題ではありません。最初のログインでそのCookieを使用するだけなので、その後、アプリには認証に使用される記憶トークンがあり、Cookieは基本的にその時点から破棄されます。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加