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

预授权不起作用

冯通
2023-03-14
<security:global-method-security pre-post-annotations="enabled">
    <security:expression-handler ref="expressionHandler" />
</security:global-method-security>
<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
    <property name="permissionEvaluator">
        <bean id="permissionEvaluator" class="myPermissionEvaluator" />
    </property>
</bean>

<security:authentication-manager id="authenticationmanager">
    <security:authentication-provider ref="authenticationprovider" />
</security:authentication-manager>
<bean id="authenticationprovider" class="myAuthenticationProvider" />
@Named
public class ChannelService {
    @PreAuthorize("isAuthenticated() and hasPermission(#channel, 'CHANNEL_WRITE')")
    public void writeMessage(Channel channel, String message) { ... }
}

EDIT做了一些更多的测试:当我只配置secure-annotations=“enabled”时,基于角色的安全性工作。此外,配置pre-postannotations=“enabled”时,既不安全也不预授权。当我只配置前-后注释时,它仍然不起作用。

编辑2

更多的测试:只有secured_annotations=“enabled”,对channelservice的调用通过Cglib2AopProxy,只要我激活前-后注释,调用就会直接进入channelservice。没有拦截器,没有代理,什么都没有。

我有点绝望了...

编辑3

我调试了我的测试,这里是spring-security的部分

2012-04-12 13:36:46,171 INFO  [main] o.s.s.c.SpringSecurityCoreVersion - You are running with Spring Security Core 3.1.0.RELEASE
2012-04-12 13:36:46,174 INFO  [main] o.s.s.c.SecurityNamespaceHandler - Spring Security 'config' module version is 3.1.0.RELEASE
2012-04-12 13:36:49,042 DEBUG [main] o.s.s.a.m.DelegatingMethodSecurityMetadataSource - Caching method [CacheKey[mystuff.UserService; public void mystuff.UserService.serverBan(java.lang.String,mystuff.models.User,org.joda.time.DateTime)]] with attributes [user]
2012-04-12 13:36:49,138 DEBUG [main] o.s.s.a.i.a.MethodSecurityInterceptor - Validated configuration attributes
2012-04-12 13:36:49,221 DEBUG [main] o.s.s.a.m.DelegatingMethodSecurityMetadataSource - Caching method [CacheKey[mystuff.ChannelService; public void mystuff.ChannelService.writeMessage(mystuff.models.Channel,java.lang.String)]] with attributes [blubb]
2012-04-12 13:36:51,159 DEBUG [main] o.s.s.a.ProviderManager - Authentication attempt using mystuff.GlobalchatAuthenticationProvider
2012-04-12 13:36:56,166 DEBUG [Timer-1] o.s.s.a.ProviderManager - Authentication attempt using mystuff.GlobalchatAuthenticationProvider
2012-04-12 13:36:56,183 DEBUG [Timer-1] o.s.s.a.i.a.MethodSecurityInterceptor - Secure html" target="_blank">object: ReflectiveMethodInvocation: public void mystuff.ChannelService.writeMessage(mystuff.models.Channel,java.lang.String); target is of class [mystuff.ChannelService]; Attributes: [blubb]
2012-04-12 13:36:56,184 DEBUG [Timer-1] o.s.s.a.i.a.MethodSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@312e8aef: Principal: mystuff.UserId@ced1752b; Credentials: [PROTECTED]; Authenticated: true; Details: null; Not granted any authorities
Exception in thread "Timer-1" 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:88)
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:205)
    at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:59)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
    at mystuff.ChannelService$$EnhancerByCGLIB$$3ad5e57f.writeMessage(<generated>)
    at mystuff.run(DataGenerator.java:109)
    at java.util.TimerThread.mainLoop(Timer.java:512)
    at java.util.TimerThread.run(Timer.java:462)
2012-04-12 13:36:56,185 DEBUG [Timer-1] o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.access.vote.RoleVoter@1cfe174, returned: 0
2012-04-12 13:36:56,185 DEBUG [Timer-1] o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.access.vote.AuthenticatedVoter@da89a7, returned: 0
2012-04-12 13:39:54,926 INFO  [main] o.s.s.c.SpringSecurityCoreVersion - You are running with Spring Security Core 3.1.0.RELEASE
2012-04-12 13:39:54,929 INFO  [main] o.s.s.c.SecurityNamespaceHandler - Spring Security 'config' module version is 3.1.0.RELEASE
2012-04-12 13:39:54,989 INFO  [main] o.s.s.c.m.GlobalMethodSecurityBeanDefinitionParser - Using bean 'expressionHandler' as method ExpressionHandler implementation
2012-04-12 13:39:59,812 DEBUG [main] o.s.s.a.ProviderManager - Authentication attempt mystuff.GlobalchatAuthenticationProvider
2012-04-12 13:39:59,850 DEBUG [main] o.s.s.a.i.a.MethodSecurityInterceptor - Validated configuration attributes
2012-04-12 14:40:41,385 INFO [main] o.s.c.s.ClassPathXmlApplicationContext - Bean 'channelService' of type [class mystuff.ChannelService] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

共有1个答案

苏雅珺
2023-03-14

此配置与我预期的一样有效:

<bean id="securityExpressionHandler"
    class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler" /> 

<bean id="preInvocationAdvice"
    class="org.springframework.security.access.expression.method.ExpressionBasedPreInvocationAdvice"
    p:expressionHandler-ref="securityExpressionHandler" />

<util:list id="decisionVoters">
    <bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
    <bean class="org.springframework.security.access.vote.RoleVoter" />
    <bean class="org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter"
        c:pre-ref="preInvocationAdvice" />
</util:list>

<bean id="accessDecisionManager"
    class="org.springframework.security.access.vote.UnanimousBased"
    c:decisionVoters-ref="decisionVoters" />

<sec:global-method-security
    authentication-manager-ref="authenticationManager"
    access-decision-manager-ref="accessDecisionManager"
    pre-post-annotations="enabled" />

我收到日志消息:

WARN  org.springframework.security.access.expression.DenyAllPermissionEvaluator - 
    Denying user jack permission 'CHANNEL_WRITE' on object Channel[ name=null ]

和例外情况:

org.springframework.security.access.AccessDeniedException: Access is denied
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:META-INF/spring/application-context.xml")
public class SpringSecurityPrePostTest {

    @Autowired
    ChannelService channelService;

    @Test
    public void shouldSecureService() throws Exception {
        Authentication authentication = new UsernamePasswordAuthenticationToken("jack", "sparrow");
        SecurityContext securityContext = SecurityContextHolder.getContext();
        securityContext.setAuthentication(authentication);

        channelService.writeMessage(new Channel(), "test");
    }
}
public interface ChannelService {

    void writeMessage(Channel channel, String message);
}
@Component
public class ChannelServiceImpl implements ChannelService {

    private static final Logger LOG = LoggerFactory.getLogger(ChannelServiceImpl.class);

    @Override
    @PreAuthorize("isAuthenticated() and hasPermission(#channel, 'CHANNEL_WRITE')")
    public void writeMessage(Channel channel, String message) {
        LOG.info("Writing message {} to: {}" , message, channel);
    }

}
<bean id="securityExpressionHandler"
    class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler" /> 

<sec:global-method-security
    authentication-manager-ref="authenticationManager"
    pre-post-annotations="enabled">
    <sec:expression-handler ref="securityExpressionHandler" />
</sec:global-method-security>

Edit4的debug消息表明ChannelService可能根本没有代理bean,因为它被归类为不适合自动代理。这个问题解决了类似的问题--尽量不要使用@autowired或任何其他基于BeanPostProcessors的机制来设置安全检查中涉及的bean(即MyPermissionEvaluator)。

更新3:

您不能在负责安全检查的bean内使用安全资源(即服务)!这将创建一个依赖项循环,这是配置中的一个错误。您必须使用情人级访问(即DAO)来检查权限,任何不安全的东西!使用安全资源实现安全检查不是您想要做的。

如果尽管@autowired使用了不安全的资源,但事情并不像预期的那样工作,那么尝试对所有涉及安全检查的bean使用老式的XML配置风格。还要记住, 实际上是一个BeanDefinitionRegistryPostProcessor并在所有XML声明的BeanFactory中引入扫描的BeanFactory。

 类似资料:
  • 问题内容: 正在尝试在方法级别定义访问规则,但是它从未如此有效。 安全配置 ExampleController 每当我尝试使用user:user它访问/ v2 / home时,它执行得很好,是否由于“用户”没有访问权限而给我“拒绝访问”错误ROLE_ADMIN? 我实际上是在考虑在方法级别放弃访问规则并坚持使用http()ant规则,但是我必须知道为什么它对我不起作用。 问题答案: 在控制器上使用

  • 我有以下几点。 我还尝试了一系列其他的排列,似乎都不起作用。我已经检查了这部分代码是否被执行,它执行并没有错误。 编辑 忘了提一下,所有的url都不能被经过身份验证的用户访问。但是任何经过身份验证的用户都可以访问所有URL。例如,以登录,我可以点击和,这是不应该发生的。 我没有东西可以尝试了。Emm...我已经用完了。我应该检查什么?

  • 我发现了许多类似的问题,但没有一个解决了我的问题。我的问题是可以访问的函数 下面是我的spring-security.xml代码。

  • 我正在使用带Spring security的Thymeleaf模板引擎。为了使用sec:authorize功能,我还使用了Thymeleaf-Spring Security集成模块,但由于某些原因,它不起作用。我没有收到任何错误,但是html div块中的所有代码都会被执行,无论用户扮演哪个角色。 例如,当我以员工身份登录时,我也会看到“去领导”和“去系统”按钮,但我不想让员工看到这些按钮。 这是

  • 我正在使用 Artifactory 2.4.0 和 Jenkins 1.438,我有一个包含多个模块的 maven 项目。需要将所有模块(jars和一场由此产生的战争)部署到Jenkins的远程Artifactory服务器中。 我的artifactory用户管理员使用默认密码(password),我尝试在jenkins上执行的所有构建都可以正常工作。因此,当我决定更改de Artifactory管

  • 我正在学习一个关于微软文档的教程,介绍如何使用Spring Boot Starter for Azure Active Directory保护我的Spring MVC应用程序。我正在努力保护我网站的管理区域。我在控制器方法上有一个@PreAuthorize注释,我只希望admin组中的用户可以访问它。我可以得到一个登录提示,但成功登录后,我得到了该控制器方法的403。当我删除@PreAuthori