Spring Security似乎忽略了某项服务

时间:2016-06-13 08:30:39

标签: java spring spring-mvc spring-security

我正在尝试使用@PreAuthorize实现Method Security。

Spring版本:4.2.3。发布 Spring Security:4.0.3。发布

我已经实现了CustomPermissionEvaluator。我注意到它似乎工作正常,除了没有调用hasPmerission的1个服务。 我知道这是因为我从hasPermission /获取了一条日志消息,或者在错误的情况下没有得到日志:

public boolean hasPermission(Authentication authentication, Object o, Object o1) {
    logger.info("Call to hasPermission with "+o+" and "+o1);
...
}

我的Spring配置如下:

@Configuration
@ComponentScan
public class RootConfiguration {
}

MVC配置

@EnableWebMvc
@Configuration
@ComponentScan({"OntoRais.*"})
@PropertySource("classpath:application.properties")
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class MvcConfiguration extends WebMvcConfigurerAdapter{


@Bean
public ViewResolver getViewResolver(){
    InternalResourceViewResolver resolver = new InternalResourceViewResolver();
    resolver.setPrefix("/WEB-INF/views/");
    resolver.setSuffix(".jsp");
    return resolver;
}

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");

    registry.addResourceHandler("swagger-ui.html")
            .addResourceLocations("classpath:/META-INF/resources/");

    registry.addResourceHandler("/webjars/**")
            .addResourceLocations("classpath:/META-INF/resources/webjars/");
}

@Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigIn()     {
    return new PropertySourcesPlaceholderConfigurer();
}


@Bean(name="multipartResolver")
public CommonsMultipartResolver commonsMultipartResolver(){
    CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver();
    commonsMultipartResolver.setDefaultEncoding("utf-8");
    commonsMultipartResolver.setMaxUploadSize(50000000);
    return commonsMultipartResolver;
}
}

方法安全配置:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@ComponentScan
public class MethodSecurityConfiguration extends       GlobalMethodSecurityConfiguration {

@Autowired
private CustomPermissionEvaluator permissionEvaluator;

@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
    DefaultMethodSecurityExpressionHandler handler
            = new DefaultMethodSecurityExpressionHandler();
    handler.setPermissionEvaluator(permissionEvaluator);
    return handler;
}


public CustomPermissionEvaluator getPermissionEvaluator() {
    return permissionEvaluator;
}

public void setPermissionEvaluator(CustomPermissionEvaluator permissionEvaluator) {
    this.permissionEvaluator = permissionEvaluator;
}
}

初​​始化器:

@Configuration
@EnableSpringConfigured
public class MessageWebApplicationInitializer extends
    AbstractAnnotationConfigDispatcherServletInitializer {

@Override
public void onStartup(ServletContext servletContext) throws ServletException {
    servletContext.addListener(org.springframework.web.context.request.RequestContextListener.class);
    super.onStartup(servletContext);
}

@Override
protected Class<?>[] getRootConfigClasses() {
    return new Class[] { MvcConfiguration.class };
}

@Override
protected Class<?>[] getServletConfigClasses() {
    return null;
}

@Override
protected String[] getServletMappings() {
    return new String[]{"/"};
}

@Override
protected Filter[] getServletFilters() {

    return new Filter[]{new HiddenHttpMethodFilter(),
            new OpenEntityManagerInViewFilter(),
            new DelegatingFilterProxy("springSecurityFilterChain")
    };
}
}

安全配置:

@Configuration
@EnableWebSecurity
@ComponentScan
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Autowired
OntoRAISUserDetailsService ontoRAISUserDetailsService;


@Override
protected void configure(HttpSecurity http) throws Exception {
    http.
            formLogin().
            and().
            logout().
            and().
            authorizeRequests().
            antMatchers("/login").permitAll().
            anyRequest().authenticated().
            and().csrf().disable();

}

@Autowired
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(ontoRAISUserDetailsService);
    auth.authenticationProvider(authenticationProvider());

}

@Bean
public DaoAuthenticationProvider authenticationProvider() {
    DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
    authenticationProvider.setUserDetailsService(ontoRAISUserDetailsService);
    authenticationProvider.setPasswordEncoder(passwordEncoder());
    return authenticationProvider;
}


@Bean
public BCryptPasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

public OntoRAISUserDetailsService getOntoRAISUserDetailsService() {
    return ontoRAISUserDetailsService;
}

public void setOntoRAISUserDetailsService(OntoRAISUserDetailsService ontoRAISUserDetailsService) {
    this.ontoRAISUserDetailsService = ontoRAISUserDetailsService;
}

有问题的服务:

@Service
public class StakeholderService {

@Autowired
private OntopManager om;

private static final Logger logger = LoggerFactory.getLogger("OntoRais");

public OntopManager getOm() {
    return om;
}

public void setOm(OntopManager om) {
    this.om = om;
}

@PreAuthorize("hasPermission(#stakeholderType, 'Create_StakeholderType')")
public void createStakeholderType(StakeholderType stakeholderType) {
    try {
        logger.info("Create stakeholder type in service layer");
        List<OBDADataSource> sources = om.getObdaModel().getSources();
        OBDAMappingAxiom mapping = om.getObdaModel().getMapping(new URI("genertatedURI"), MappingList.StakheholderType());

        HashMap<String, String> values = new HashMap<>();
        values.put("stakeholderName", stakeholderType.getLabel());

        String query = ClassSQLHelper.generateSQLCreateSatement(mapping.getSourceQuery(), values);
        SQLHelper.executeSQL(query, sources.get(0));

    } catch (URISyntaxException e) {
        logger.error(e.getMessage());
    }
}

我从中调用服务层的控制器:

@Api(description = "Operations related to Stakeholders")
@RestController
public class StakeholderController {

@Autowired
private OntopManager om;

@Autowired
StakeholderService stakeholderService;

@Autowired
ProjectService projectService;

private static final Logger logger =     LoggerFactory.getLogger("OntoRais");

...

 /**
 * Add a new Stakeholder Type
 *
 * @param stakeholdertype The new Stakeholder to be added.
 * @return
 */
@ApiOperation(value = "Add new stakeholder type",
        notes = "",
        response = ResponseResource.class,
        responseContainer = "Object")
@JsonView(Views.Details.class)
@RequestMapping(value = "/api/stakeholder/types", method = RequestMethod.POST)
public ResponseEntity<List<StakeholderType>> addStakeholderType(@RequestBody StakeholderType stakeholdertype) {
    logger.info("Add Stakeholder type in controller");
    getStakeholderService().createStakeholderType(stakeholdertype);
    return getStakeholderTypes();
}

使用method = POST调用api / stakeholder / types时 这是我的调试输出:

Add Stakeholder type in controller 
Create stakeholder type in service layer 
INSERT INTO prefix_http_www_ontorais_de_stakeholdertype(id,stakeholderName) VALUES(DEFAULT,'TESTEWRTERETE'); 

如您所见,hasPermission中的日志不存在 - &gt;不叫。 我可以看到该方法是从其他服务对象中的其他方法sercurity注释中调用的。

一个类似的服务,它正确地调用hasPermission作为预期只是为了比较:

@Service
public class OrganisationService {

private static final Logger logger = LoggerFactory.getLogger("OntoRais");
@Autowired
private OntopManager om;

@Autowired
private ProjectService projectService;

...

@PreAuthorize("hasAuthority('Add_Organisation')")
public void addOrganisation(Organisation organisation) {
    List<OBDADataSource> sources = om.getObdaModel().getSources();

    OBDAMappingAxiom mapping = null;
    try {
        mapping = om.getObdaModel().getMapping(new URI("genertatedURI"), MappingList.OrganisationMapping());
    } catch (URISyntaxException e) {
        e.printStackTrace();
    }

    HashMap<String, String> valueMap = new HashMap<>();
    valueMap.put("organisationName", organisation.getName());
    valueMap.put("organisationDescription", organisation.getDescription());

    String query = ClassSQLHelper.generateSQLCreateSatement(mapping.getSourceQuery(), valueMap);

    SQLHelper.executeSQL(query, sources.get(0));
}

非常欢迎任何有关我错误/遗失/失明的提示。

1 个答案:

答案 0 :(得分:0)

好的,我发现了问题和解决方案。

问题是我的CustomPermissionEvaluator依赖于StakeholderService中的方法。即使该方法没有安全,但这导致Spring无法代理该对象,因此阻止了任何安全检查。

即使在PermissionEvaluator中使用服务层对象也是一个坏主意,也许有人可以详细说明确切含义,因为我肯定不是春季服务专家