Я пытаюсь реализовать метод Security с помощью @PreAuthorize.Spring Security, похоже, игнорирует определенную услугу
Spring Версия: 4.2.3.Release Spring Security: 4.0.3.Release
я реализовал CustomPermissionEvaluator. Я заметил, что он работает нормально, за исключением 1 службы, где hasPmerission не вызывается. Я знаю это, потому что я получаю сообщение протоколирования от 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 Config
@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;
}
}
Метод безопасности Config:
@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;
}
}
Initializer:
@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")
};
}
}
Security Config:
@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();
}
При вызове API/заинтересованных сторон/типов»с методом POST = Это мой отладочный вывод:
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 нет -> не называется. Я вижу, что метод вызывается из моих других аннотаций 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));
}
Любые намеки на то, что я делаю неправильно/отсутствует/слеп для очень приветствуются спасибо.
Бенедикт
'OntoRais. *' Не действительное имя пакета.'StakeholderService' не реализует интерфейс, поэтому для того, чтобы' @ PreAuthorize' работал с библиотекой, такой как cglib или javassist, должен быть включен. В чем разница между вашими услугами? – zeroflagL
Хорошо изменил мой компонент сканирования в '@ComponentScan ({ "OntoRais.api", "OntoRais.datalayer.database.service", "OntoRais.security", "OntoRais.datalayer.ontology.ontop", «OntoRais .datalayer.ontology.service ", " OntoRais.config " })'. Ни один из моих служб не реализует интерфейс. Разве проблема не возникает во всех моих сервисах? Я не могу найти разницы в сервисах. Чтобы быть уверенным, я включу рабочую службу в исходный вопрос. – bwright
Если никакая служба не реализует интерфейс, то проблема, конечно же, является чем-то другим. Я думаю, что '@ComponentScan ({« OntoRais »})' должно быть достаточно. В 'StakeholderController', что такое код для' getStakeholderService() '? Если он не вернет защищенный прокси-сервер, это будет проблемой. Вы можете добавить точку останова в свой метод сервиса и посмотреть на стек вызовов. – zeroflagL