2017-02-13 11 views
-1

私はウェブをかなり研究しましたが、私の問題に解決策はまだありません。私の場合に合わないものを使っているすべての人。私のscenerio:春のセキュリティ - コントローラからの値を読み取る

ユーザーはpost(email: "admin"、password: "admin")を送信します。入力が正しいかどうかをチェックし、そのトークンがヘッダ/

私はコントローラからSpring認証プロセスへの値を渡す部分についています。以下は

私の設定です:ここ

@Configuration 
@EnableWebSecurity 
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) 
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 


    @Autowired 
    private TokenAuthenticationProvider tokenAuthenticationProvider; 


    @Autowired 
    @Override 
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
     auth.authenticationProvider(this.tokenAuthenticationProvider); 
    } 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http 
       .authorizeRequests() 
       .antMatchers("/login").permitAll() 
       .anyRequest().authenticated().and() 
       .csrf().disable(); 
    } 
} 

は私のコントローラです:

@RestController 
public class LoginController { 

    @Autowired 
    private AuthenticationManager authenticationManager; 

    @RequestMapping(value = "/login", method = RequestMethod.POST) 
    public ResponseEntity<?> login(@RequestBody LoginCredentials payload){ 

     Authentication authentication = this.authenticationManager.authenticate(
       new UsernamePasswordAuthenticationToken(
         payload.getUsername(), 
         payload.getPassword() 
       ) 
     ); 

     SecurityContextHolder.getContext().setAuthentication(authentication); 
     return ResponseEntity.ok("OK"); 
    } 
} 

、これは

@Component 
public class TokenAuthenticationProvider implements AuthenticationProvider { 


    @Override 
    public Authentication authenticate(Authentication authentication) throws AuthenticationException { 

     if(authentication.getName().equals("admin") && authentication.getCredentials().equals("admin")) { 
      List<GrantedAuthority> grantedAuths = new ArrayList<>(); 
      grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER")); 
      grantedAuths.add(new SimpleGrantedAuthority("ROLE_ADMIN")); 
      return new UsernamePasswordAuthenticationToken(authentication.getName(), authentication.getCredentials(), grantedAuths); 
     } else { 
      return null; 
     } 
    } 

    @Override 
    public boolean supports(Class<? extends Object> authentication) { 
     return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication)); 
    } 
} 

Imが資格情報を使用してPOSTリクエストを行うと、これは私の認証プロバイダであります答えイム取得:

{ 
    "timestamp": 1486995388844, 
    "status": 403, 
    "error": "Forbidden", 
    "exception": "org.springframework.security.authentication.ProviderNotFoundException", 
    "message": "Access Denied", 
    "path": "/login" 
} 
+4

Spring Securityをハッキングするのではなく、意図したとおりにフレームワークを使用してください。認証を行うためのフィルタを作成し、コントローラを使用してロックしないようにしてください。 –

+0

@ M.Deinum。厳密には、フィルターで受信した認証情報を処理し、認証されていない認証を作成し、次にAuthenticationManagerによって処理され、役割を解決し、Authoriを作成する必要がありますzed認証を行い、トークンを返します。その後のリクエストでは、トークンは別のフィルタ内のトークンストア(db)に対して解決され、認証された認証(トークンが有効な場合)を作成し、 'SecurityContextHolder.getContext()。setAuthentication'を設定します。 –

+0

ok 2つのフィルタが必要です。ログイン(ユーザー名、パスワード)からの入力が正しいかどうかをチェックし、有効なトークン(dbまたはJWTに格納されている可能性があります)を出したら、トークンが添付されているリクエスト? – filemonczyk

答えて

2

ログインに対処するために新しいコントローラを作成することを選択したのは興味深いですが、基本的にはSpring Securityが行う作業を複製しています。あなたは認証プロバイダを呼び出すことで認証されるユーザの資格情報をチェックするカスタムコントローラ(特定のエンドポイント)にHTTP POSTリクエストを送信します。これはすでにSpring Securityモジュール(特定のエンドポイントに対してPOSTを実行する必要があり、セキュリティコンテナによって定義された認証プロバイダが呼び出され、ユーザにアクセスを許可するかどうかを決定します)。

私はあなたがそのコントローラを必要としないと信じています:セキュリティコンテナにいくつかの余分な設定が必要なので、始めましょう!

ところで、Springの設定が主にJavaで書かれていても、Spring Securityの設定はまだ完全なJavaをサポートしておらず、依然としてほとんどの場合XMLである必要があります。

特定のエンドポイントがヒットしたとき(そのHTTP POST要求で)、認証プロセスを初期化するようにSpring Securityを設定できます。次のようにXMLでは、これが行われます:

<http> 
    <form-login login-processing-url="/perform_login"/> 

    ...(other configuration) 
</http> 

私はdocumentationでそれを見つけることを試みているが、私は同等のJavaの設定を見つけることができません。私たちは、このようなHttpSecurityオブジェクトにformLogin()メソッドを呼び出すことができます。

protected void configure(HttpSecurity http) throws Exception { 
    http 
    .authorizeRequests() 
     .anyRequest().authenticated() 
     .and() 
    .formLogin() 
     .loginPage("/login") 
     .permitAll(); 
} 

が、ログイン処理のURLを設定するには、何のJavaメソッドはなさそうです。 loginPage()メソッドは、ログインが必要な場合にユーザーを送信するためのURLを指定します(これは私たちが探しているものではありません)。

ログイン処理URLを設定しないと、セキュリティコンテナはデフォルトのものである/j_spring_security_checkを使用します。

これで、認証資格を/perform_loginにポストすることができ、Springセキュリティは認証フィルタに対してそれらを使用してアクセスを許可するかどうかを決定します。

完了ですか?未だに。 デフォルトのusernamepasswordのパラメータは、j_usernamej_passwordと呼ばれます。したがって、これらのパラメータを/perform_loginにPOSTする必要があります。幸いなことに、これらの2つの名前を設定することができます(XMLで再び - 申し訳ありません):

<http> 
    <form-login login-processing-url="/perform_login"/> 
       username-parameter="email" 
       password-parameter="password" 

    ...(other configuration) 
</http> 

今設定されています。 (あなたはCSRFトークンをしたい場合またはそれ以上)の二つのパラメータでHTTP POSTを発行して - すなわちメールパスワード/に perform_login、我々は適切に認証することができます(と私たちはと呼ばれるさらに別のクラスを作成する必要はありませんでしたLoginCredentialsのようにしてください

+0

答えに感謝しますが、カスタムログインページなどにリダイレクトしたくありません。私は、ユーザーが所与のエンドポイントを使用してログインすることを期待しています。信用がOKならば、彼は401を取得しなければ、さらなるリクエストのためのトークンを取得します。 – filemonczyk

+0

私はあなたが望むエンドポイントとしてlogin-processing-urlを設定するだけで、そこにあなたの詳細をPOSTします(電子メールパラメータとパスワードパラメータ)。 –

+0

私はlogin-processing-urlタグがあなたにそのページにリダイレクトされるのではなく、そのページへのPOSTリクエストが認証プロセスを初期化することを誤解していると思います。 –

関連する問題