2017-01-13 8 views
0

私はSpringフレームワークとSpring MVCを使ってRESTエンドポイントを作成するWebアプリケーションを持っています。認証は、Java EEセキュリティ(特にActive Directoryに基づくWildfly 9のセキュリティレルム)を使用してコンテナによって提供され、ロールはアプリケーションデータベースからロードされます。通常のサーブレットAPIを使用してユーザーの詳細を利用できるようにするために、フィルタによってリクエストラッパーが適用されています。JSR-250(@RolesAllowed)アノテーションの使用Spring MVCとコンテナ認証

のweb.xml:

<web-app ... version="3.1"> 

    <security-constraint> 
     <web-resource-collection> 
      <web-resource-name>Unauthenticated Resources</web-resource-name> 
      <url-pattern>/favicon.ico</url-pattern> 
      <url-pattern>/NoAccess.html</url-pattern> 
      <url-pattern>/login</url-pattern> 
      <url-pattern>/css/*</url-pattern> 
      <url-pattern>/font/*</url-pattern> 
      <url-pattern>/images/*</url-pattern> 
      <url-pattern>/js/*</url-pattern> 
      <url-pattern>/lib/*</url-pattern> 
      <url-pattern>/partials/*</url-pattern> 
     </web-resource-collection> 
    </security-constraint> 

    <security-constraint> 
     <web-resource-collection> 
      <web-resource-name>All Resources</web-resource-name> 
      <url-pattern>/*</url-pattern> 
     </web-resource-collection> 
     <auth-constraint> 
      <role-name>*</role-name> 
     </auth-constraint> 
    </security-constraint> 

    <login-config> 
     <auth-method>FORM</auth-method> 
     <realm-name>App Realm</realm-name> 
     <form-login-config> 
      <form-login-page>/Login.jsp</form-login-page> 
      <form-error-page>/NoAccess.html</form-error-page> 
     </form-login-config> 
    </login-config> 

    <security-role> 
     <role-name>*</role-name> 
    </security-role> 

</web-app> 

SecurityFilter.java

@WebFilter(urlPatterns = { "*" }) 
public class SecurityFilter implements Filter { 

    ... 

    @Override 
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 
     HttpServletRequest httpRequest = (HttpServletRequest) request; 
     HttpServletResponse httpResponse = (HttpServletResponse) response; 

     // Don't wrap unauthenticated requests 
     if (httpRequest.getRemoteUser() == null) { 
      chain.doFilter(httpRequest, httpResponse); 
      return; 
     } 

     Person user = this.personRepository.findByLogin(httpRequest.getRemoteUser()); 
     if (user != null) { 
      List<String> roles = this.personRepository.getRoles(user.getId()); 
      HttpServletRequest wrappedRequest = new RequestWrapper(httpRequest, user, roles); 
      chain.doFilter(wrappedRequest, httpResponse); 
     } else { 
      httpResponse.sendRedirect(httpRequest.getContextPath() + "/NoAccess.html"); 
     } 
    } 
} 

認証が動作し、コントローラ内、私はrequest.getUserPrincipal()request.isUserInRole("SYSTEM_ADMIN")を行うことができますし、彼らが正常に戻ります。今私はアプリケーションに権限を追加したいと思います。私はJSR-250 @RolesPermitted注釈を使用してコントローラのメソッドに承認ルールを適用したいと思います。私は別の設定ファイル/クラスにすべてのルールをリストする必要はありません。コントローラの例:もちろん

@RestController 
@RequestMapping("/people") 
public class PersonController { 

    ... 

    @RolesAllowed({Role.SYSTEM_ADMIN, Role.DEPARTMENT_ADMIN, Role.SYSTEM_AUDITOR, Role.AUDITOR}) 
    @RequestMapping 
    public List<Person> listPeople(HttpServletRequest request) { 
     return this.personRepository.getPeople(); 
    } 
} 

これは自分自身で何もしないので、私は@EnableWebSecurity@EnableGlobalMethodSecurity(jsr250Enabled = true)で設定クラスを追加しました。そのリソースにヒットしたら、エラーorg.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContextが出ます。十分に公正なので、私はhttps://gist.github.com/virgium03/86938e43219bc28632d0の例に従っていますが、私は同じエラーが発生し続けます。フィルタがフィルタチェーンに追加されることはないと考えられます。

私は多くのチュートリアルとその記事を読んだことがありますが、それらはすべて同じことを言っているし、私にとってはうまくいきません。私が紛失している単純なものがなければなりません。結局のところ、すべての情報は、Spring Securityが承認決定を下すためのものです。それは可能(可能性がありますか?)私はここで簡単な何かを欠いている。すべてのヘルプは非常に高く評価されています!

編集

私は春のセキュリティコンテキストを移入するために私SecurityFilterクラスに次のコードを追加しています。それは動作しますが、私はこれが理想的な解決策ではないと感じています。

List<GrantedAuthority> authorities = roles.stream() 
     .map(SimpleGrantedAuthority::new) 
     .collect(Collectors.toList()); 
PreAuthenticatedAuthenticationToken auth = new PreAuthenticatedAuthenticationToken(user, "", authorities); 
auth.setDetails(new WebAuthenticationDetails(wrappedRequest)); 
auth.setAuthenticated(true); 
SecurityContextHolder.getContext().setAuthentication(auth); 

答えて

1

設定した認証プロバイダに問題があります。 PreAuthenticatedAuthenticationProviderを使用しており、authenticateメソッドから既存の認証トークンを返します。したがって、プリンシパルがnullの場合、リクエストを無視して他のプロバイダに認証させます。

認証

公共認証認証(認証認証) を含むAuthenticationException認証所与PreAuthenticatedAuthenticationTokenをスロー。認証オブジェクトに含まれる プリンシパルがnullの場合、他のプロバイダが認証するために、 という要求は無視されます。

基本的に、認証トークンを生成する別のAuthenticationProviderを設定し、このトークンをSecurityContextに設定する必要があります。

+0

しかし、J2eePreAuthenticatedProcessingFilterのソースを見ると、HttpRequestから認証オブジェクトを作成し、それを(AbstractPreAuthenticatedProcessingFilterを介して)セキュリティコンテキストに置くことを示しています。これが私が必要とするものではありませんか? – Doughnuts

+0

私はJ2eePreAuthenticatedProcessingFilterのソースを見て、それは認証オブジェクトを作成していません。 HttpRequestからユーザープリンシパルを返すだけです。 –

+0

https://github.com/spring-projects/spring-security/blob/master/web/src/main/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilter.java(J2eePreAuthenticatedProcessingFilterのスーパークラス) – Doughnuts

関連する問題