问题:
我已经实现了以下应用程序事件侦听器,它可以捕获身份验证(成功和失败两种情况)和授权(失败)。但是,虽然授权成功,但不会触发偶数。我跟踪了代码,发现AbstractSecurityInterceptor类中的publishAuthorizationSuccess始终为false,因此它不会发布AuthorizedEvent。

环境:
在JUnit上运行

我的程序的执行顺序:
运行MySampleApp-> SomeService-> ResourcePatternBaseVoter-> AbstractSecurityInterceptor-> SecurityAuditor(授权成功后不会触发)

我的代码和配置如下所示:

MySampleApp.class

public class MySampleApp{
@Test
public void test2() {
    Authentication authentication = providerManager
            .authenticate(new UsernamePasswordAuthenticationToken("admin", "admin"));
    SecurityContextHolder.getContext().setAuthentication(authentication);
    logger.debug(someService1.someMethod6());
}


SomeService.java

@Service
public class SomeService1 {
@Secured("rpb:reports:a.b.c:create")
public String someMethod6() {
    return String.valueOf(Math.random());
}


ResourcePatternBaseVoter.java

@Component
public class ResourcePatternBaseVoter implements org.springframework.security.access.AccessDecisionVoter<Object> {

private static final Log logger = LogFactory.getLog(ResourcePatternBaseVoter.class);

@Autowired
private ResourcePatternBaseAuthorizer resourcePatternBaseAuthorizer;

@Override
public boolean supports(ConfigAttribute attribute) {
    if ((attribute.getAttribute() != null) && attribute.getAttribute().startsWith("rpb:")) {
        logger.debug("support attribute: " + attribute.getAttribute());
        return true;
    } else {
        logger.debug("not support attribute: " + attribute.getAttribute());
        return false;
    }
}

@Override
public boolean supports(Class<?> clazz) {
    return true;
}

@Override
public int vote(Authentication authentication, Object secureObject, Collection<ConfigAttribute> attributes) {
    /*   doSomething        */

    return ACCESS_GRANTED;
}


}

SecurityAuditor.java

@Component
public class SecurityAuditor implements ApplicationListener<AuthorizedEvent> {

@Override
public void onApplicationEvent(AuthorizedEvent event) {
    logger.info("Here");
}


myAcl.xml

<bean id="methodAccessDecisionManager"
    class="org.springframework.security.access.vote.AffirmativeBased">
    <constructor-arg name="decisionVoters">
        <list>
            <bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
            <bean class="com.ibm.gbsc.ty.acl.rpb.ResourcePatternBaseVoter" />
        </list>
    </constructor-arg>
</bean>


AbstractSecurityInterceptor.class

    if (publishAuthorizationSuccess) {
        publishEvent(new AuthorizedEvent(object, attributes, authenticated));
    }

最佳答案

This article让我开始了,但是Spring Security 4.1.3中不再存在该bean。但是,我发现它隐藏在FilterChainProxy中。

不知道这种骇客有多丑,但是可​​以工作:

@Configuration
@EnableWebSecurity
@EnableJpaAuditing
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private ApplicationContext applicationContext;

    @EventListener
    public void handle(ContextRefreshedEvent event) {
        FilterChainProxy proxy = applicationContext.getBean(FilterChainProxy.class);
        for (Filter f : proxy.getFilters("/")) {
            if (f instanceof FilterSecurityInterceptor) {
                ((FilterSecurityInterceptor)f).setPublishAuthorizationSuccess(true);
            }
        }
    }
    ...
}


然后,我的侦听器最终收到AuthorizedEvent:

@Component
public class AppEventListener implements ApplicationListener {
    private static final Logger logger = LoggerFactory.getLogger(AppEventListener.class);

    @Override
    @EventListener(value = {AuthorizedEvent.class})
    public void onApplicationEvent(ApplicationEvent event)
    {
        if (event instanceof InteractiveAuthenticationSuccessEvent) {
            Authentication auth =  ((InteractiveAuthenticationSuccessEvent)event).getAuthentication();
            logger.info("Login success: " + auth.getName() + ", details: " + event.toString());
        } else if (event instanceof AbstractAuthenticationFailureEvent) {
            logger.error("Login failed: " + event.toString());
        } else if (event instanceof AuthorizedEvent) {
            Authentication auth =  ((AuthorizedEvent)event).getAuthentication();
            logger.debug("Authorized: " + auth.getName() + ", details: " + event.toString());
        } else if (event instanceof AuthorizationFailureEvent) {
            Authentication auth =  ((AuthorizationFailureEvent)event).getAuthentication();
            logger.error("Authorization failed: " + auth.getName() + ", details: " + event.toString());
        }
    }
}

关于spring-security - 即使在Spring Security上也无法获取成功授权,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36051224/

10-14 06:30