16

以下に示す構成のSpring 3アプリケーションがあります。ログインしていないユーザーがページにアクセスしようとすると、醜いスタック トレースでAccess is Denied例外が発生します。この例外を処理し、スタック トレースをダンプさせないようにするにはどうすればよいですか。独自の access-denied-handler を実装しましたが、それが呼び出されません。

リクエストされたリソースのタイプに基づいて、カスタム エラー メッセージまたはページを表示したいと考えています。これが私の春の設定です。

Spring に access-denied-handler を呼び出させるにはどうすればよいですか。これが私の春の構成です

 <security:http auto-config='true'>
    <security:intercept-url pattern="/static/**" filters="none"/>
    <security:intercept-url pattern="/login" filters="none"/>

      <security:intercept-url pattern="/**" access="ROLE_USER" />

      <security:form-login login-page="/index"
            default-target-url="/home" always-use-default-target="true"
            authentication-success-handler-ref="AuthenticationSuccessHandler"        
            login-processing-url="/j_spring_security_check" 
            authentication-failure-url="/index?error=true"/>

       <security:remember-me key="myLongSecretCookieKey" token-validity-seconds="1296000" 
            data-source-ref="jdbcDataSource" user-service-ref="AppUserDetailsService" />

       <security:access-denied-handler ref="myAccessDeniedHandler" />   

    </security:http>

    <bean id="myAccessDeniedHandler"
         class="web.exceptions.handlers.AccessDeniedExceptionHandler">
      <property name="errorPage" value="/public/403.htm" />
    </bean>

この例外を処理するためのカスタム クラスを以下に示します。

public class AccessDeniedExceptionHandler implements AccessDeniedHandler
{

    private String errorPage;

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response,
            AccessDeniedException arg2) throws IOException, ServletException {
        response.sendRedirect(errorPage);
    }

       public void setErrorPage(String errorPage) {
       if ((errorPage != null) && !errorPage.startsWith("/")) {
            throw new IllegalArgumentException("errorPage must begin with '/'");
        }
        this.errorPage = errorPage;
    }

}

このアプリケーションを実行すると、これがエラーになります。スタック トレースと Spring デバッグ ログの一部のみを貼り付けます。

20:39:46,173 DEBUG AffirmativeBased:53 - Voter: org.springframework.security.access.vote.RoleVoter@5b7da0d1, returned: -1
20:39:46,173 DEBUG AffirmativeBased:53 - Voter: org.springframework.security.access.vote.AuthenticatedVoter@14c92844, returned: 0
20:39:46,178 DEBUG ExceptionTranslationFilter:154 - Access is denied (user is anonymous); redirecting to authentication entry point
org.springframework.security.access.AccessDeniedException: Access is denied
    at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:71)
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:204)

この問題を解決するにはどうすればよいですか? まず、春がその例外をスローするのを止めたいと思います。それでもスローされる場合は、フラグを立てずに処理したいと思います。

更新: web.xml の一部も添付しました。

<!-- Hibernate filter configuration -->

<filter>
        <filter-name>HibernateFilter</filter-name>
        <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>HibernateFilter</filter-name> 
        <url-pattern>/*</url-pattern>       
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>

<filter>
  <filter-name>springSecurityFilterChain</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
  <filter-name>springSecurityFilterChain</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

    <!--Dispatcher Servlet -->

   <servlet>
     <servlet-name>rowz</servlet-name>
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
     <load-on-startup>1</load-on-startup>
   </servlet>
4

7 に答える 7

12

あなたの構成では、あなたのサイトに URL を入力するとき、ユーザーは常に認証される必要があります:

<security:intercept-url pattern="/**" access="ROLE_USER" />

ログインページに入るときにユーザーが認証されないようにする必要があると思います:

<security:intercept-url pattern="/your-login-page-url" access="ROLE_ANONYMOUS" />
<security:intercept-url pattern="/your-login-process-url" access="ROLE_ANONYMOUS" />
<security:intercept-url pattern="/your-login-failure-url" access="ROLE_ANONYMOUS" />
<security:intercept-url pattern="/**" access="ROLE_USER" />

URL の like:/login/startを使用する場合、以下/login/errorを使用/login/failureできます。

<security:intercept-url pattern="/login/**" access="ROLE_ANONYMOUS" />
<security:intercept-url pattern="/**" access="ROLE_USER" />

アップデート:

この構成により、認証されていない (匿名の) すべてのユーザーをログイン ページにリダイレクトし、すべての認証済みユーザーをAccessDeniedHandlerにリダイレクトするフレームワークが作成されます。AccessDeniedExceptionは、フレームワークのコア部分の 1 つであり、無視することはお勧めできません。Spring Security 構成の一部のみを提供する場合、これ以上の支援は困難です。

フレームワークによってどの例外がスローされるのか、デフォルトでどのように処理されるのか、その理由についての詳細な説明については、 ExceptionTranslationFilterの JavaDoc を必ずお読みください。

可能であれば、AuthenticationSuccessHandlerRememberMeAuthenticationFilterAccessDeniedHandlerなど、追加したカスタム パーツをできるだけ多く削除してみて、問題が解決しないかどうかを確認してください。最小限の構成を取得し、新しい機能を段階的に追加して、エラーの原因を確認してください。

あなたの質問で言及していない重要なことの1つは、このエラーメッセージの結果は何ですか? あなたは得HTTP 500ますか?それともHTTP 403?それともログインページにリダイレクトされますか?

質問で述べたように、ユーザーが認証されておらず、ログインページにリダイレクトされた場合、それが意図されている方法ではありません。レベルがSpring Securityクラスに設定されているため、 ExceptionTranslationFilter:172によってログに記録されたエラーメッセージが表示されるようです。DEBUGもしそうなら、それはそれが意図されている方法でもあり、エラーをログに記録したくない場合は、Spring Secyruty クラスのログレベルを上げるだけです。

更新 2:

ログインページを表示してログインを処理するページですべての SpringSecurity チェックをスキップするには、のパターンがおよび に設定された属性とfilters="none"一致する必要があります。login-pagelogin-processing-urlauthentication-failure-ur<security:form-login />

<security:http auto-config='true'>
  <security:intercept-url pattern="/static/**" filters="none"/>
  <security:intercept-url pattern="/index" filters="none"/>
  <security:intercept-url pattern="/j_spring_security_check" filters="none"/>
  <security:intercept-url pattern="/**" access="ROLE_USER" />

  <security:form-login login-page="/index"
        default-target-url="/home" always-use-default-target="true"
        authentication-success-handler-ref="AuthenticationSuccessHandler"        
        login-processing-url="/j_spring_security_check" 
        authentication-failure-url="/index?error=true"/>

   <security:remember-me key="myLongSecretCookieKey" token-validity-seconds="1296000" 
        data-source-ref="jdbcDataSource" user-service-ref="AppUserDetailsService" />

   <security:access-denied-handler ref="myAccessDeniedHandler" />   

</security:http>
于 2011-09-07T15:33:46.407 に答える
7

AccessDeniedHandlerユーザーがログインし、リソースへのアクセス許可がない場合に呼び出されます( source here )。ユーザーがログインしていないときにログインページのリクエストを処理したい場合は、 security-contextで設定するだけです:

<http ... entry-point-ref="customAuthenticationEntryPoint">

customAuthenticationEntryPoint を定義します。

<beans:bean id="customAuthenticationEntryPoint" class="pl.wsiadamy.webapp.controller.util.CustomAuthenticationEntryPoint">
</beans:bean>

ヒントと戦おうとしないでくださいExceptionTranslationFilter。効果なしでオーバーライドしようとしましたorg.springframework.security.web.access.ExceptionTranslationFilter

<beans:bean id="exceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
  <beans:property name="authenticationEntryPoint"  ref="customAuthenticationEntryPoint"/>
  <beans:property name="accessDeniedHandler" ref="accessDeniedHandler"/>
</beans:bean>
<beans:bean id="accessDeniedHandler"
 class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
  <beans:property name="errorPage" value="/accessDenied.htm"/>
</beans:bean>

ref="customAuthenticationEntryPoint"呼び出されませんでした。

于 2013-05-25T10:51:07.423 に答える
3

次の方法で Spring Access 拒否ページを追加しました: Spring Frame Work: 3.1 Spring Security: 3.1, Java 1.5+

*-security.xml のエントリ:

<security:access-denied-handler error-page="/<My Any error page controller name>" />

例:

<security:access-denied-handler error-page="/accessDeniedPage.htm" />

エラーページは常に「/」で始まります

コントローラのエントリ:

@Controller
public class RedirectAccessDenied {

    @RequestMapping(value = "/accessDeniedPage.htm", method = RequestMethod.GET)
    public String redirectAccessDenied(Model model) throws IOException, ServletException {
        System.out.println("############### Redirect Access Denied Handler!");
        return "403";
    }
}

ここで 403 は私の JSP 名です。

于 2012-09-10T08:52:01.080 に答える
1

プログラムによる解決策:

@Order(1)
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    //
    // ...
    //

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.exceptionHandling().accessDeniedHandler(new AccessDeniedHandlerImpl() {
            @Override
            public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
                super.handle(request, response, accessDeniedException);
                accessDeniedException.printStackTrace();
            }
        });

        //
        // ...
        //

    }

}
于 2016-01-21T15:36:07.970 に答える
0

web.xmlが転送要求をサポートしていることを確認できますか?

errorPageはFORWARDリクエストであり、ほとんどの場合web.xmlではREDIRECTSのみをサポートしています。考えてみれば、あなたのコードは私には問題ないように見えます。

編集済み

別の観点とこれは、作業コードからのみ取得されます。AuthenticatedVoterクラスをご覧ください

注釈を無効にする

<global-method-security pre-post-annotations="disabled"
    secured-annotations="disabled" access-decision-manager-ref="accessDecisionManager">
</global-method-security>

フィルタをバイパスする

<http auto-config="true" use-expressions="true"
    access-decision-manager-ref="accessDecisionManager"
    access-denied-page="/accessDenied">
    <intercept-url pattern="/appsecurity/login.jsp" filters="none" />
    <intercept-url pattern="/changePassword" filters="none" />
    <intercept-url pattern="/pageNotFound" filters="none" />
    <intercept-url pattern="/accessDenied" filters="none" />
    <intercept-url pattern="/forgotPassword" filters="none" />
    <intercept-url pattern="/**" filters="none" />


    <form-login login-processing-url="/j_spring_security_check"
        default-target-url="/home" login-page="/loginDetails"
        authentication-failure-handler-ref="authenticationExceptionHandler"
        authentication-failure-url="/?login_error=t" />
    <logout logout-url="/j_spring_security_logout"
        invalidate-session="true" logout-success-url="/" />
    <remember-me />
    <!-- Uncomment to limit the number of sessions a user can have -->
    <session-management invalid-session-url="/">
        <concurrency-control max-sessions="1"
            error-if-maximum-exceeded="true" />
    </session-management>
</http>

カスタム決定投票者

<bean id="customVoter" class="xyz.appsecurity.helper.CustomDecisionVoter" />

アクセス決定マネージャー

<!-- Define AccessDesisionManager as UnanimousBased -->
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
    <property name="decisionVoters">
        <list>
            <ref bean="customVoter" />
            <!-- <bean class="org.springframework.security.access.vote.RoleVoter" 
                /> -->
            <bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
        </list>
    </property>
</bean>

認証例外ハンドラ

<bean id="authenticationExceptionHandler"
    class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler">
    <property name="exceptionMappings">
        <props>
            <!-- /error.jsp -->
            <prop
                key="org.springframework.security.authentication.BadCredentialsException">/?login_error=t</prop>
            <!-- /getnewpassword.jsp -->
            <prop
                key="org.springframework.security.authentication.CredentialsExpiredException">/changePassword</prop>
            <!-- /lockedoutpage.jsp -->
            <prop key="org.springframework.security.authentication.LockedException">/?login_error=t</prop>
            <!-- /unauthorizeduser.jsp -->
            <prop
                key="org.springframework.security.authentication.DisabledException">/?login_error=t</prop>
        </props>
    </property>
</bean>
于 2011-09-04T11:29:37.650 に答える
0

「/index」であるログインページにログインしていないユーザーをSpringがリダイレクトしようとしているようですが、それ自体が保護されたURLです。

もう 1 つの可能性は、/public/403.html を表示しようとすることですが、これもセキュリティ構成によって保護されています。

次のエントリを追加して試していただけますか?

<security:intercept-url pattern="/login" filters="none" />
<security:intercept-url pattern="/public/**" filters="none" />
于 2011-09-09T04:28:13.847 に答える