복붙노트

[SPRING] 메소드 레벨 보안으로 AccessDenied 처리

SPRING

메소드 레벨 보안으로 AccessDenied 처리

나는 다음과 같이 스프링 보안으로 보안 된 메소드를 가지고있다 :

@PreAuthorize("hasRole('add_user')")
public void addUser(User user) ;

enoguh 권한이없는 사용자가이를 호출하려고 시도하는 경우 , accessDenied 예외가 throw됩니다.

org.springframework.security.access.AccessDeniedException: Access is denied

이것은 예상되는 것이지만 질문은 왜 정의 된 액세스 거부 처리기

in security.xml 구성 파일이 작동하지 않습니다.

<access-denied-handler error-page="accessDenied"/>

나는 액세스 권한이없는 사용자가 addUser 버튼을 누르려고 할 때 AccessDenied Exception이 Throw되어 원하는 동작이지만 사용자 isn이 서비스 addUser를 호출하려고 할 때 작동하지 않음을 의미합니다. xml에 구성된대로 액세스가 거부 된 예외로 리디렉션되지 않습니다.

이 예외가 throw 될 때 거부 된 페이지에 액세스하도록 사용자가 자동으로 리디렉션되어서는 안됩니까? 아니면 코드에서 이러한 동작을 명시 적으로 정의해야합니까?

조언 해주십시오.

JSF 2.1과 ICEFaces 2에서 Spring Security 3.0.5를 사용하고 있습니다.

업데이트 : applicationSecurity.xml :

<beans:beans xmlns="http://www.springframework.org/schema/security"  
    xmlns:beans="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
          http://www.springframework.org/schema/security
          http://www.springframework.org/schema/security/spring-security-3.0.4.xsd
          http://www.springframework.org/schema/util
          http://www.springframework.org/schema/util/spring-util-3.1.xsd">


        <!-- Enable @pre, @post spring security method level annotations -->
        <global-method-security pre-post-annotations="enabled" />   


        <http use-expressions="true"  auto-config="true" access-denied-page="/accessDenied">

     <session-management session-fixation-protection="none"/>

        <remember-me  token-validity-seconds="1209600"/>


        <intercept-url pattern="/accessDenied" access="permitAll"/>        
        <intercept-url pattern="/login" access="permitAll"/>
        <intercept-url pattern="/j_spring_security_check" access="permitAll" />


        <intercept-url pattern="/faces/javax.faces.resource/**" access="permitAll" />
        <intercept-url pattern="/xmlhttp/**" access="permitAll" />
        <intercept-url pattern="/resources/**" access="permitAll" />        
        <intercept-url pattern="/scripts/**" access="permitAll" />
        <intercept-url pattern="/images/**" access="permitAll" />
        <intercept-url pattern="/css/**" access="permitAll" />


        <!-- All pages requires authentication (not anonymous user) -->

        <intercept-url pattern="/**" access="isAuthenticated()" />
        <intercept-url pattern="/faces/**" access="isAuthenticated()" />


        <form-login default-target-url="/"   
        always-use-default-target="true"            
            login-processing-url="/j_spring_security_check"         
            login-page="/login"
            authentication-failure-url="/login?login_error=1"                                                               
        />

        <logout logout-url="/logout" logout-success-url="/login" />     
    </http>

    <authentication-manager alias="authenticationManager">          
      <authentication-provider user-service-ref="userDetailsServiceImpl"/>    
    </authentication-manager>


    </beans:beans>

업데이트 2 : 예외 전에 디버그 :

DEBUG [http-bio-8080-exec-1] (PrePostAnnotationSecurityMetadataSource.java:93) - @org.springframework.security.access.prepost.PreAuthorize(value=hasRole('add_user')) found on specific method: public void com.myapp.service.impl.UserServiceImpl.addUser(com.myapp.domain.User) throws java.lang.Exception,org.springframework.security.access.AccessDeniedException
DEBUG [http-bio-8080-exec-1] (DelegatingMethodSecurityMetadataSource.java:66) - Adding security method [CacheKey[com.myapp.service.impl.UserServiceImpl; public abstract void com.myapp.service.UserService.addUser(com.myapp.domain.User) throws java.lang.Exception,org.springframework.security.access.AccessDeniedException]] with attributes [[authorize: 'hasRole('add_user')', filter: 'null', filterTarget: 'null']]
DEBUG [http-bio-8080-exec-1] (AbstractSecurityInterceptor.java:191) - Secure object: ReflectiveMethodInvocation: public abstract void com.myapp.service.UserService.addUser(com.myapp.domain.User) throws java.lang.Exception,org.springframework.security.access.AccessDeniedException; target is of class [com.myapp.service.impl.UserServiceImpl]; Attributes: [[authorize: 'hasRole('add_user')', filter: 'null', filterTarget: 'null']]
DEBUG [http-bio-8080-exec-1] (AbstractSecurityInterceptor.java:292) - Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@c650d918: Principal: org.springframework.security.core.userdetails.User@db344023: Username: user@mycomp.com; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: access_viewUsers; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@fffde5d4: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: E6BBAC0CD4499B1455227DC6035CC882; Granted Authorities: access_viewUsers
DEBUG [http-bio-8080-exec-1] (AffirmativeBased.java:53) - Voter: org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter@1d1e082e, returned: -1
DEBUG [http-bio-8080-exec-1] (AffirmativeBased.java:53) - Voter: org.springframework.security.access.vote.RoleVoter@1eab12f1, returned: 0
DEBUG [http-bio-8080-exec-1] (AffirmativeBased.java:53) - Voter: org.springframework.security.access.vote.AuthenticatedVoter@71689bf1, returned: 0

해결법

  1. ==============================

    1.스프링 보안 문서에 따르면, 엘리먼트의 access-denied-page 속성의 사용자는 스프링 3.0 이상에서 사용되지 않을 것이다.

    스프링 보안 문서에 따르면, 엘리먼트의 access-denied-page 속성의 사용자는 스프링 3.0 이상에서 사용되지 않을 것이다.

    우리는 앱에서 다음을 수행합니다.

    여기 내 XML : AccessDeniedHandlerApp 확장 'AccessDeniedHandlerImpl`

    <http auto-config='true'>
        <intercept-url pattern="/views/**" access="ROLE_USER" />
        <form-login login-page="/Login.jsp" authentication-success-handler-ref="loginSuccessFilter"
                    authentication-failure-handler-ref="loginFailureFilter" />
        <logout logout-success-url="/home" />
        <access-denied-handler ref="customAccessDeniedHandler"/>
    </http>
    
    <beans:bean id="customAccessDeniedHandler" class="org.demo.security.AccessDeniedHandlerApp"/>
    

    여기에 내 액세스가 거부 된 컨트롤러가 있습니다. 이전에 게시 했어야했는데 미안합니다. 액세스가 거부 된 페이지가 표시되게하려면 리디렉션을 사용해야했습니다.

    @Controller
    public class AccessDeniedController {
        private static Logger logger = Logger.getLogger(AccessDeniedController.class);
    
        @RequestMapping(value = "/securityAccessDenied")
        public String processAccessDeniedException(){
            logger.info("Access Denied Handler");
            return "redirect:/securityAccessDeniedView";
        }
    
        @RequestMapping(value = "/securityAccessDeniedView")
        public String displayAccessDeniedView(){
            logger.info("Access Denied View");
            return "/SecurityAccessDenied";
        }
    

    이 방법으로 문제가 해결되지 않고 계속 파고들 수 있다면 알려 주시기 바랍니다. 방금 여기에서 다시 테스트 했으므로 트릭을 수행해야합니다.     }

  2. ==============================

    2.나는 같은 문제에 직면 해 있으며 같은 문제와 관련된 또 다른 질문을 올렸다. 몇 시간 동안 파고 들자 마침내 내 문제의 해결책을 찾았습니다. 나는이 질문이 2 년 이상 된 것을 알고 있지만 누군가 다른 사람에게 가치가있는 경우에 대비하여 정보로 업데이트 할 것이라고 생각했습니다.

    나는 같은 문제에 직면 해 있으며 같은 문제와 관련된 또 다른 질문을 올렸다. 몇 시간 동안 파고 들자 마침내 내 문제의 해결책을 찾았습니다. 나는이 질문이 2 년 이상 된 것을 알고 있지만 누군가 다른 사람에게 가치가있는 경우에 대비하여 정보로 업데이트 할 것이라고 생각했습니다.

    요컨대, SimpleMappingExceptionResolver가 예외를 처리하고 기본 매핑으로이를 해결하고있는 것으로 나타났습니다. 결과적으로 액세스 거부 처리기로 리디렉션되는 ExceptionTranslationFilter에 스택을 버블 할 예외는 없었습니다.

    더 자세한 정보는 메소드 레벨 보안을 사용하는 액세스 거부 처리자를 무시하는 스프링 보안을 참조하십시오.

  3. ==============================

    3.Spring Security는 사용자가 리소스에 액세스 할 수있는 권한이없는 경우에만 액세스가 거부 된 페이지로 리디렉션합니다. 이것은 사용자가 인증되었지만 허용 된 역할이없는 경우입니다.

    Spring Security는 사용자가 리소스에 액세스 할 수있는 권한이없는 경우에만 액세스가 거부 된 페이지로 리디렉션합니다. 이것은 사용자가 인증되었지만 허용 된 역할이없는 경우입니다.

    그러나 문제가 인증이 아니라 인증 일 때, Spring Security는 액세스가 거부 된 페이지가 아니라 로그인 페이지로 리디렉션됩니다 (사용자가 직접 인증 할 수 있도록).

    규칙에서 "isAuthenticated ()"를 확인하는 규칙이 있으므로 액세스 거부 페이지로 리디렉션되지 않고 로그인 페이지로 리디렉션됩니다.

    희망이 도움이됩니다.

  4. from https://stackoverflow.com/questions/7916460/handling-accessdenied-with-method-level-security by cc-by-sa and MIT license