当前位置: 首页 > 知识库问答 >
问题:

Spring Security拒绝访问`@Security`方法,尽管已授予权限

蒋文光
2023-03-14
@Secured(SUPERADMIN_ROLE)
@SpringView(name = AdminHomeView.NAME)
class AdminHomeView : DemoViewWithLabel(){
    companion object {
        const val NAME = "admin/home"
    }

    override val labelContent = "This is the protected admin section. You are authenticated and authorized."
}
VerticalLayout(Label(labelContent))

因此,如果我以superadmin角色的身份登录,我就可以很好地访问这个视图。

但是,让我们做一个小的改变,重写一个方法...

@Secured(SUPERADMIN_ROLE)
@SpringView(name = AdminHomeView.NAME)
class AdminHomeView : DemoViewWithLabel(){
    companion object {
        const val NAME = "admin/home"
    }

    override val labelContent = "This is the protected admin section. You are authenticated and authorized."

    override fun enter(event: ViewChangeListener.ViewChangeEvent?) {
        super.enter(event)
    }
}

这会给我一个AccessDeniedException...我不明白为什么。

Secure object: ReflectiveMethodInvocation: public void ch.cypherk.myapp.ui.views.admin.AdminHomeView.enter(com.vaadin.navigator.ViewChangeListener$ViewChangeEvent);
  target is of class [ch.cypherk.myapp.ui.views.admin.AdminHomeView];
  Attributes: [Superadmin]
Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@a6801701:
  Principal: ch.cypherk.myapp.model.auth.MyUserDetails@6e4c5c5b;
  Credentials: [PROTECTED];
  Authenticated: true; Details: null;
  Granted Authorities: RIGHT_MANAGER, Superadmin 
Voter: org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter@7ddc2dd1, returned: 0  
Voter: org.springframework.security.access.vote.RoleVoter@75d3fbb7, returned: 0  
Voter: org.springframework.security.access.vote.AuthenticatedVoter@391740fc, returned: 0
org.springframework.security.access.AccessDeniedException: Access is denied
    at org.springframework.security.access.vote.AbstractAccessDecisionManager.checkAllowIfAllAbstainDecisions(AbstractAccessDecisionManager.java:70)
    at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:89)
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233)
    at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:65)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
    at ch.cypherk.myapp.ui.views.admin.AdminHomeView$$EnhancerBySpringCGLIB$$ae16a97c_4.enter(<generated>)
    at com.vaadin.navigator.Navigator.performNavigateTo(Navigator.java:778)
    at com.vaadin.navigator.Navigator.lambda$navigateTo$9a874efd$1(Navigator.java:702)
    at com.vaadin.navigator.ViewBeforeLeaveEvent.navigate(ViewBeforeLeaveEvent.java:54)
    at com.vaadin.navigator.View.beforeLeave(View.java:79)
    at com.vaadin.navigator.Navigator.runAfterLeaveConfirmation(Navigator.java:730)
    at com.vaadin.navigator.Navigator.navigateTo(Navigator.java:701)
  at ...

为什么?!!

希望能得到一些帮助来解决这个问题。

共有1个答案

东门翰
2023-03-14

简而言之

授予的权限不显示role_-prefix,因此将被rolevoter忽略。

用具有空前缀的自定义实现替换rolevoter解决了这个问题。

Vaadin是一个单页框架,Vaadin 8引用视图的方式很糟糕,即在根url上使用#!(例如https:// : /#!foo/bar/baz/... )。

#之后不会向服务器发送任何内容,这意味着我们无法区分对/的访问和对/#!foo/bar/baz/...的访问

因此,我们不能使用Spring Security性来保护对视图的访问。

访问这些观点本身是由瓦丁保护的,而不是Spring。SpringViewProvider将找不到用户不应该访问的视图(因此,用户无法在那里导航)。

但是,只要我们在该视图上调用一个方法,Spring security就会启动并执行访问检查。正是这些检查失败了,因为授予的authorites没有预期的“role_”前缀Spring。(我原以为这只是一个约定,但事实并非如此;rolevoter实际上忽略了不显示前缀的权限,因此必须这样做,或者必须提供自己的rolevoter。)

解决办法相对简单。

@Configuration
@EnableGlobalMethodSecurity(
    securedEnabled = true,
    prePostEnabled = true,
    proxyTargetClass = true
)
class GlobalSecurityConfiguration : GlobalMethodSecurityConfiguration(){
    override fun accessDecisionManager(): AccessDecisionManager {
        return (super.accessDecisionManager() as AffirmativeBased).apply {
            decisionVoters.replaceAll {
                when(it){
                    is RoleVoter -> MyRoleVoter()
                    else -> it
                }
            }
        }
    }
}
class MyRoleVoter : RoleVoter(){
    init {
        rolePrefix = ""
    }
}
 类似资料:
  • 配置: 我正在使用JWT,所以我有一个过滤器来创建基于它的用户: 我的userDetailsService填充GrantedAuthorities:

  • 我对spring security&oauth2相当陌生。作为学习的一部分,我试图设置一个OAuth2授权服务器,并保护RESTendpoint免受未经授权的访问。 代码 资源服务器 ProductController.java 未经授权API可以正常工作 如果我们只使用权限(@preauthorize(“hasauthorize('...')”))进行授权,它可以正常工作 作用域在到达oauth

  • 问题内容: 我看过许多类似的问题,因此表明我已经检查了基础知识。当然,这并不意味着我没有错过任何显而易见的东西。:-) 我的问题是:为什么我拒绝具有特权的用户访问权限,而我却已经在其中输入密码并被授予访问权限?(为了完整起见,我尝试输入错误的密码只是为了确保MySQL客户端在程序启动时拒绝我访问。) 背景: 通过ssh登录到运行MySQL服务器的计算机的外壳,我以root用户身份登录: 太棒了 我

  • 我已经创建了一个webview应用程序,在那里我扫描二维码。在移动和桌面浏览器上一切正常,但在应用程序中,我得到。 我在下面分享一些代码: 我也尝试了这里和这里建议的解决方案,但它对我不起作用。

  • 我在编写部署在Tomcat上的Grails应用程序时遇到了一些奇怪的问题。 在创建简单的测试控制器之后,我想在包com中编写测试内容 我有个例外: 类java.io.FileNotFoundException消息/home/user/domains/domain.com/public_html/the-file-name.txt(Brak dost rpu) 我已经将chmod设置为777到。而是

  • 我正在heroku上做一个新项目,使用mysql(他们有一个名为JawsDB的插件,它给我一个mysql主机、用户名和密码)。(更新:我也试过使用他们的其他mysql插件ClearDB,我也遇到了同样的问题) 我可以像这样连接到数据库(并且我可以“show databases”来查看其中的内容): 问题:当我创建数据库时,我得到: 我已尝试授予所有特权,如下所示: 但这给了我: 我也尝试过创建用户