Ich versuche Method Security mit @ PreAuthorize zu implementieren.Spring Security scheint einen bestimmten Service zu ignorieren
Frühling Version: 4.2.3.Release Spring Security: 4.0.3.Release
Ich habe eine CustomPermissionEvaluator umgesetzt. Ich habe festgestellt, dass es funktioniert, außer für 1 Dienst, wo die hasPmerission nicht aufgerufen wird. Ich weiß das, weil ich das eine Logging-Nachricht von hasPermission/oder in der falschen Fall nicht bekommen, das Protokoll erhalten:
public boolean hasPermission(Authentication authentication, Object o, Object o1) {
logger.info("Call to hasPermission with "+o+" and "+o1);
...
}
My Spring-Konfiguration ist wie folgt:
@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;
}
}
Methode Security 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;
}
Der Dienst in Frage:
@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());
}
}
Und die Steuerung von dem ich die Dienstschicht nennen:
@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();
}
Wenn api/Stakeholder/types“mit Aufruf der Methode = POST Dies ist meine Debug-Ausgabe:
Add Stakeholder type in controller
Create stakeholder type in service layer
INSERT INTO prefix_http_www_ontorais_de_stakeholdertype(id,stakeholderName) VALUES(DEFAULT,'TESTEWRTERETE');
Wie Sie das Protokoll von hasPermission nicht vorhanden zu sehen ist -> nicht genannt. Ich kann sehen, dass die Methode von meinen anderen Methoden-Sicherheitsannotationen in anderen Dienstobjekten aufgerufen wird.
Ein ähnlicher Dienst, die hasPermission richtig ruft als Vergleich nur für erwartete:
@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));
}
Irgendwelche Hinweise auf das, was ich tue, falsch/fehlt/bin blind für sehr willkommen Dank.
Benedict
'OntoRais. *' Ist nicht ein gültiger Paketname'StakeholderService' implementiert keine Schnittstelle. Um' @ PreAuthorize' zu verwenden, muss eine Bibliothek wie cglib oder javassist eingebunden werden. Was ist der Unterschied zwischen Ihren Dienstleistungen? – zeroflagL
Ok änderte meine Component-Scan '@ComponentScan ({ "OntoRais.api", "OntoRais.datalayer.database.service", "OntoRais.security", "OntoRais.datalayer.ontology.ontop", „OntoRais .datalayer.ontology.service ", " OntoRais.config " })'. Keines meiner Dienste implementiert eine Schnittstelle. Sollte das Problem nicht in allen meinen Diensten auftreten? Ich kann keinen Unterschied in den Diensten finden. Ich werde nur einen Arbeitsdienst in die ursprüngliche Frage aufnehmen, um sicher zu gehen. – bwright
Wenn kein Dienst eine Schnittstelle implementiert, ist das Problem natürlich etwas anderes. Ich denke '' ComponentScan ({"OntoRais"}) 'sollte reichen. In 'StakeholderController', wie lautet der Code für' getStakeholderService() '? Wenn es den gesicherten Proxy nicht zurückgibt, wäre das das Problem. Sie können in Ihrer Servicemethode einen Haltepunkt hinzufügen und sich den Aufruf-Stack ansehen. – zeroflagL