Spring 使用方法级安全性处理拒绝访问

Spring 使用方法级安全性处理拒绝访问,spring,spring-security,Spring,Spring Security,我有一个用spring security保护的方法,如下所示: @PreAuthorize("hasRole('add_user')") public void addUser(User user) ; 如果没有enoguh权限的用户试图调用它 ,将引发accessDenied异常: org.springframework.security.access.AccessDeniedException: Access is denied 这是预期的,但问题是,为什么定义的拒绝访问处理程序 在se

我有一个用spring security保护的方法,如下所示:

@PreAuthorize("hasRole('add_user')")
public void addUser(User user) ;
如果没有enoguh权限的用户试图调用它 ,将引发accessDenied异常:

org.springframework.security.access.AccessDeniedException: Access is denied
这是预期的,但问题是,为什么定义的拒绝访问处理程序

在security.xml中,配置文件不工作:

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

根据spring安全文档,元素的“拒绝访问页面”属性的用户在spring 3.0及更高版本中已被弃用

我们在应用程序中执行以下操作:

  • 通过扩展Spring安全框架的
    AccessDeniedHandlerImpl
    ,创建自定义拒绝访问处理程序
  • 调用
    setErrorPage
    方法,输入将显示访问被拒绝页面的控制器的名称
  • 在我们的例子中,我们将用户的帐户锁定在自定义处理程序中——任何用户都没有理由获得拒绝访问异常,除非他们正在做不应该做的事情。我们还记录他们试图访问的内容,等等
  • 调用
    super.handle(\u请求,\u响应,\u异常)位于处理程序的末尾。Spring将控制转发到上面#2中列出的控制器

    这是我的访问被拒绝控制器-我应该早点发布-对此表示抱歉。为了打开拒绝访问页面,我必须使用重定向:

    @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";
        }
    
    请让我知道,如果这不能解决它,我会继续挖掘-我刚刚在本地测试了它,这应该可以做到。
    }

    仅当用户没有访问资源的权限时,Spring Security才会重定向到“拒绝访问”页面。也就是说,当用户经过身份验证但不具有允许的角色时

    但当问题不是授权而是身份验证时,Spring Security会重定向到登录页面(让用户自己进行身份验证),而不是拒绝访问页面

    由于您有一个规则检查规则中的“isAuthenticated()”,因此不会将您重定向到拒绝访问页面,而是重定向到登录页面


    希望能有所帮助。

    我自己也遇到了同样的问题,并发布了另一个与同样问题相关的问题。经过几个小时的反复研究,我终于找到了解决问题的办法。我知道这个问题已经2年多了,但我想我会用信息更新它,以防它对其他人有价值

    简而言之,我注意到,
    SimpleMappingExceptionResolver
    正在处理异常并使用默认映射解析它。因此,没有任何异常可以将堆栈冒泡到
    ExceptionTranslationFilter
    ,它将重定向到
    拒绝访问处理程序


    请参阅以获取更多信息。

    也许提供了一些线索?此示例是自定义实现,因为他想在出现拒绝访问时向会话添加额外数据,所以我不需要此自定义,我只需要默认行为。请发布完整的安全配置。@fresh\u dev:您所说的“不工作”到底是什么意思?@Ralph,更新了问题,解释了不起作用的情况。上面的代码对我不起作用,会抛出accessDeniedException,但用户不会重定向到拒绝访问页面@jcurtin它对我也不起作用,抛出了异常,但用户没有重定向到自定义拒绝访问处理程序ref,知道为什么吗?@fresh_dev-这对你们有帮助吗?正如我之前告诉过你们的,它首先不会进入AccessDeniedHandlerApp类,这是关键问题。
    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
    
    public class AccessDeniedHandlerApp extends AccessDeniedHandlerImpl {
        private static Logger logger = Logger.getLogger(AccessDeniedHandlerApp.class);
    
        private static final String LOG_TEMPLATE = "AccessDeniedHandlerApp:  User attempted to access a resource for which they do not have permission.  User %s attempted to access %s";
    
         @Override
         public void handle(HttpServletRequest _request, HttpServletResponse _response, AccessDeniedException _exception) throws IOException, ServletException {
             setErrorPage("/securityAccessDenied");  // this is a standard Spring MVC Controller
    
             // any time a user tries to access a part of the application that they do not have rights to lock their account
             <custom code to lock the account>
             super.handle(_request, _response, _exception);
    }
    
    <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";
        }