微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

spring – PreAuthorize不起作用

我正在编写套接字服务器(没有web应用程序!)应用程序,并希望使用基于方法的安全性来处理我的ACL需求.我按照一个小教程找到了spring security by example

到目前为止我配置:

ecurity:global-method-security pre-post-annotations="enabled">
    ecurity:expression-handler ref="expressionHandler" />
ecurity:global-method-security>
ecurity.access.expression.method.DefaultMethodSecurityExpressionHandler">
    ecurity:authentication-manager id="authenticationmanager">
    ecurity:authentication-provider ref="authenticationprovider" />
ecurity:authentication-manager>
@H_502_10@

使用服务bean:

@Named
public class ChannelService {
    @PreAuthorize("isAuthenticated() and hasPermission(#channel,'CHANNEL_WRITE')")
    public void writeMessage(Channel channel,String message) { ... }
}
@H_502_10@

一切都编译,应用程序启动并正常工作,但没有访问控制.我的调试日志显示我的Evaluator永远不会被调用.

当我尝试使用@Secured注释类似的东西时,注释被评估并且访问被拒绝.但基于角色的简单安全性不足以满足我的要求.

编辑
做了一些更多的测试:当我只配置secure-annotations =“enabled”时,基于角色的安全性工作.当在ADDITION中配置pre-post-annotations =“enabled”时既不安全也不预授权.当我只配置预注释后,它仍然无法正常工作.

EDIT2

更多测试:
只有secured_annotations =“enabled”对我的channelservice的调用通过cglib2AopProxy
一旦我激活了预注释后,呼叫就会直接落在频道服务中.没有拦截器,没有代理,没有.

我变得有点绝望……

EDIT3

在这里调试记录我的测试是spring-security的一部分

只有secure-annotations =“enabled”

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 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(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
@H_502_10@

带有预注释=“启用”

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
@H_502_10@

据我所知,这个日志输出spring没有意识到我的bean需要被代理,所以它们不是,所以我没有得到安全性.

EDIT4

我调试了完整的sprint启动…(那是一个大日志),我发现:

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)
@H_502_10@

有没有办法找出原因?因为据我所知.因为@preauthorize bean应该符合条件.只有secure-annotations =“enabled”我得到一个后期处理日志.

最佳答案
这个配置对我来说就像预期的那样:

ecurityExpressionHandler"
    class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler" /> 

ecurity.access.expression.method.ExpressionBasedPreInvocationAdvice"
    p:expressionHandler-ref="securityExpressionHandler" />

Voters">
    ecurity.access.Vote.AuthenticatedVoter" />
    ecurity.access.Vote.RoleVoter" />
    ecurity.access.prepost.PreInvocationAuthorizationAdviceVoter"
        c:pre-ref="preInvocationAdvice" />
ecurity.access.Vote.UnanimousBased"
    c:decisionVoters-ref="decisionVoters" />

ecurity
    authentication-manager-ref="authenticationManager"
    access-decision-manager-ref="accessDecisionManager"
    pre-post-annotations="enabled" />
@H_502_10@

我收到了日志消息:

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

还有一个例外:

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

一个简单的测试:

@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");
    }
}
@H_502_10@

我做的一件事就是在服务和JDK代理上使用接口而不是cglib

public interface ChannelService {

    void writeMessage(Channel channel,String message);
}
@H_502_10@

和:

@Component
public class ChannelServiceImpl implements ChannelService {

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

    @Override
    @PreAuthorize("isAuthenticated() and hasPermission(#channel,String message) {
        LOG.info("Writing message {} to: {}",message,channel);
    }

}
@H_502_10@

UPDATE1:

使用这个简化的配置,我得到相同的结果:

ecurityExpressionHandler"
    class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler" /> 

ecurity
    authentication-manager-ref="authenticationManager"
    pre-post-annotations="enabled">
    ecurityExpressionHandler" />
ecurity>
@H_502_10@

UPDATE2:

来自Edit4的调试消息表明channelService可能根本没有代理bean,因为它被归类为not eligible for auto-proxying. This qiestion回答了类似的问题 – 尽量不要使用@Autowired或任何其他基于BeanPostProcessors的机制来设置安全检查中涉及的bean(即myPermissionEvaluator).

UPDATE3:

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

如果尽管使用@Autowired没有安全资源的东西不能按预期工作,请尝试使用旧式XML配置样式来处理安全检查中涉及的所有bean.还要记住< context:component-scan />实际上是一个BeanDeFinitionRegistryPostProcessor,并且在XML中声明的所有bean已经存在之后,将扫描的bean引入beanfactory.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐