Autowired in CustomInterceptor getting null(Spring Boot) [duplicate] - java

This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 7 years ago.
I want to make a check in database when i receive a request. So i did a Interceptor like below,
CustomInterceptor.java
#Component
public class CustomInterceptor extends HandlerInterceptorAdapter {
#Autowired
private DatabaseService databaseService;
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//Set Request Attribute(TODO)
LogService.info(this.getClass().getName(), "New Request URI is:" + request.getRequestURI());
return true;
}
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
String authToken = request.getHeader("AuthToken");
boolean isValidRequest = databaseService.checkIfTokenIsValid(authToken);
}
}
Application.class:
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
// protected Properties props = new Properties();
//
// public Application() {
// props.setProperty("error.path", "/error");
//// props.setProperty("error.whitelabel.enabled", "false");
//// props.setProperty("org.springframework.web", "DEBUG");
// }
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
// application.properties(props);
return application.sources(Application.class);
}
#Override
public void onStartup(final ServletContext servletContext) throws ServletException {
LogService.info(Application.class.getName(), "Loading Service...");
super.onStartup(servletContext);
LogService.info(Application.class.getName(), "Service Started");
}
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(Application.class, args);
}
DatabasService.java
#Service
public class DatabaseService {
#Autowired
private ApplicationProperties properties;
private final JdbcTemplate defaultJdbcTemplate;
#Autowired
public DatabaseService(
#Qualifier("dataSource") DataSource dataSource) {
defaultJdbcTemplate = new JdbcTemplate(dataSource);
}
public boolean checkIfTokenIsValid() {
//Perform Check
}
}
CustomWebConfiguration.java
#Configuration
#EnableWebMvc
public class CustomWebConfiguration extends WebMvcConfigurerAdapter {
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
"classpath:/META-INF/resources/", "classpath:/resources/",
"classpath:/static/", "classpath:/public/"};
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!registry.hasMappingForPattern("/**")) {
registry.addResourceHandler("/**").addResourceLocations(
CLASSPATH_RESOURCE_LOCATIONS);
}
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new CustomInterceptor())
.addPathPatterns("/**");
}
}
But i get NullPointer At: boolean isValidRequest = databaseService.checkIfTokenIsValid(authToken);
What is wrong here, why cannot spring Autowire the Databaseservice in Interceptor?
Note: Autowire works fine everywhere else, but not in the interceptor.
Solution (Thanks to M. Deinum)
Change the CustomWebConfiguration.java like below;
#Configuration
#EnableWebMvc
public class CustomWebConfiguration extends WebMvcConfigurerAdapter {
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
"classpath:/META-INF/resources/", "classpath:/resources/",
"classpath:/static/", "classpath:/public/"};
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!registry.hasMappingForPattern("/**")) {
registry.addResourceHandler("/**").addResourceLocations(
CLASSPATH_RESOURCE_LOCATIONS);
}
}
#Bean
public CustomInterceptor customInterceptor() {
return new CustomInterceptor();
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(customInterceptor())
.addPathPatterns("/**");
}
}

Spring will only autowire beans it knows about, you are creating the instance yourself outside the control of Spring.
Either inject a CustomInterceptor into your configuration class or add a #Bean method to make it a Spring managed instance. Then use that instance to add it to the list of interceptors.

It is OK to use #SpringBootApplication on your main class, however don't you miss #EnableAutoConfiguration and #ComponentScan on the same class to tell Spring Boot to look for other components and services automatically?

Related

NullPointerException for Springboot #Autowired component in interceptor [duplicate]

This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 8 months ago.
I have a component that's the main job is to return a Jedis instance, and it looks like the following:
#Component
public class JedisConfig {
private Jedis jedis;
public JedisConfig() {
jedis = new Jedis("localhost", 6379);
}
public Jedis getJedis() {return jedis;}
}
I then use the Jedis instance to do some stuff in my interceptor's preHandler:
public class AuthInterceptor implements HandlerInterceptor {
#Autowired
private JedisConfig jc;
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Jedis jedis = jc.getJedis();
// do some other stuff with jedis below
}
}
But I get a NullPointerException when calling jc.getJedis() and I don't understand why it's happening.
On a related note, I did pretty much the exact same thing in a unit test and it runs fine:
#Autowired
private JedisConfig jc;
#Test
public void testJedis(){
Jedis jedis = jc.getJedis();
jedis.set("user", "role");
assertThat(jedis.get("user"),is("role"));
}
Here's How I added the interceptor to the registry:
#Configuration
public class WebConfig implements WebMvcConfigurer {
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthInterceptor())
.addPathPatterns("/user/roleChange");
}
}
If anyone knows how to fix this please let me know. Thank you so much!
The AuthInterceptor is not a Spring bean, and the JedisConfig is not autowired and is null. As long as the interceptor is used in the #Configuration class, you can perform autowiring there and encapsulating the JedisConfig interceptor.
#RequiredArgsConstructor // either use Lombok or write the constructor by yourself
public class AuthInterceptor implements HandlerInterceptor {
private final JedisConfig jc;
}
#Configuration
public class WebConfig implements WebMvcConfigurer {
#Autowired
private JedisConfig jc;
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthInterceptor(jc))
.addPathPatterns("/user/roleChange");
}
}
Alternatively, you can treat the AuthInterceptor as a component and autowire it in the WebConfig class:
#Component
public class AuthInterceptor implements HandlerInterceptor {
#Autowired
private JedisConfig jc;
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Jedis jedis = jc.getJedis();
...
}
}
#Configuration
public class WebConfig implements WebMvcConfigurer {
#Autowire
private AuthInterceptor authInterceptor;
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor)
.addPathPatterns("/user/roleChange");
}
}

Configure WebRequestInterceptor in Spring Configuration

I am trying to use WebRequestInterceptor but i don't know how can i configure it in spring boot, as if I implement WebMvcConfigurer interface it requires a HandlerInterceptor object so i cannot assign my interceptor to it. Any help would be highly appreciated.
Interceptor class:
public class CustomerStateInterceptor implements WebRequestInterceptor {
#Resource(name = "customerStateRequestProcessor")
private CustomerStateRequestProcessor customerStateRequestProcessor;
#Override
public void preHandle(WebRequest webRequest) {
customerStateRequestProcessor.process(webRequest);
}
#Override
public void postHandle(WebRequest webRequest, ModelMap modelMap) {
//unimplemented
}
#Override
public void afterCompletion(WebRequest webRequest, Exception e) {
//unimplemented
}
}
and config class:
#Configuration
public class InterceptorConfig implements WebMvcConfigurer {
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new CustomerStateInterceptor()); // <-- Error here.
}
}
You supposed to implement HandlerInterceptor from org.springframework.web.servlet package and not WebRequestInterceptor.
Update
You can just wrap with WebRequestHandlerInterceptorAdapter:
#Configuration
public class InterceptorConfig implements WebMvcConfigurer {
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(
new WebRequestHandlerInterceptorAdapter(
new CustomerStateInterceptor()));
}
}
Add filter class to your package and please try the code below -
public class RequestValidateFilter extends GenericFilterBean {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
try {
request = new RequestWrapper(httpServletRequest);
chain.doFilter(request, response);
} catch (Exception e) {
throw new ServletException();
}
}
}
FilterClass :
#Configuration
public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.addFilterBefore(requestValidateFilter(), BasicAuthenticationFilter.class);
http.authorizeRequests().antMatchers("/projectname/**").authenticated();
http.addFilterAfter(responseValidateFilter(), BasicAuthenticationFilter.class);
}
private RequestValidateFilter requestValidateFilter() {
return new RequestValidateFilter();
}
private ReponseValidateFilter responseValidateFilter() {
return new ReponseValidateFilter();
}
}

Spring Cloud OAuth2Authentication returns NullPointerException

I'm slowly moving into understanding Spring Cloud Security. I've created an authorization service and it works when authorizing and returning a token, but doesn't return any current user details when using that token, when getting these from OAuth2Authentication. This two lines return an NPE:
userInfo.put("user", user.getUserAuthentication().getPrincipal());
userInfo.put("authorities", AuthorityUtils.authorityListToSet(user.getUserAuthentication().getAuthorities()));
OAuth2Authentication user isn't instantiated and is null, while I understood that it should be by default instantiated by Spring Security. Maybe I am missing some configuration beans? Thanks in advance!
Application.class
#SpringBootApplication
#RestController
#EnableResourceServer
#EnableAuthorizationServer
public class AuthorizationServiceApplication {
#RequestMapping(value = {"/user"}, produces = "application/json")
public Map <String, Object> user (OAuth2Authentication user) {
Map <String, Object> userInfo = new HashMap <>();
userInfo.put("user", user.getUserAuthentication().getPrincipal());
userInfo.put("authorities", AuthorityUtils.authorityListToSet(user.getUserAuthentication().getAuthorities()));
return userInfo;
}
public static void main (String[] args) {
SpringApplication.run(AuthorizationServiceApplication.class, args);
}
}
OAuth2Config.class
#Configuration
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
#Value("${token.secret}")
private String secret;
private AuthenticationManager authenticationManager;
private UserDetailsService userDetailsService;
public OAuth2Config (AuthenticationManager authenticationManager, UserDetailsService userDetailsService) {
this.authenticationManager = authenticationManager;
this.userDetailsService = userDetailsService;
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("eagleeye")
.secret(secret)
.authorizedGrantTypes("refresh_token", "password", "client_credentials")
.scopes("webclient", "mobileclient");
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
}
WebSecurityConfigurer.class
#Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
#Override
#Bean
public AuthenticationManager authenticationManagerBean () throws Exception {
return super.authenticationManagerBean();
}
#Override
#Bean
public UserDetailsService userDetailsServiceBean() throws Exception {
return super.userDetailsServiceBean();
}
// TODO: implemented DB stuff
#Override
protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder
.inMemoryAuthentication()
.withUser("deniss").password("deniss1").roles("USER")
.and()
.withUser("oksana").password("oksana").roles("USER, ADMIN");
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setSessionAttributeName("_csrf");
return repository;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().csrfTokenRepository(csrfTokenRepository());
}
}
In the end I got it working like this:
Application.class
#SpringBootApplication
#RestController
#EnableResourceServer
public class AuthorizationServiceApplication {
private final Logger log = LoggerFactory.getLogger(this.getClass());
#RequestMapping("/user")
public Principal user(Principal user) {
log.info("User information display for User: " + user.getName());
return user;
}
#Bean
UserDetailsService userDetailsService() {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("deniss").password("deniss").roles("USER").build());
return manager;
}
public static void main (String[] args) {
SpringApplication.run(AuthorizationServiceApplication.class, args);
}
}
OAuth2Config.java
#Configuration
#EnableAuthorizationServer
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
//TODO: refactor to recieve this info from config server
#Value("${token.secret}")
private String secret;
#Autowired
private AuthenticationManager authenticationManager;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("eagleeye")
.secret(secret)
.authorizedGrantTypes("refresh_token", "password", "client_credentials")
.scopes("webclient", "mobileclient");
}
}
SecurityConfigurer.class
#Configuration
#EnableGlobalAuthentication
public class SecurityConfigurer extends GlobalAuthenticationConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
// TODO: implemented DB stuff
#Override
public void init(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder.userDetailsService(this.userDetailsService);
}
}
I met the same problem, it seems a bug of new version. I changed Spring Boot 1.5.9.RELEASEļ¼ŒSpring Cloud Edgware.RELEASE backed to Spring Boot 1.4.4.RELEASEļ¼ŒSpring Cloud Camden.SR5, the problem disappeared.
Set security.oauth2.resource.filter-order=3 configuration property to restore the ordering used in previous versions. See enter link description here for more details.

Spring controller: How to use property ${..} in #RequestMapping?

I already found questions with answers but they don't help me.
I have a web servlet project where I use a Spring Controller (4.2.5) and Spring Security (4.0.2). I don't use Spring Boot.
My project works fine.
But now my task is this:
Make #RequestMapping(value={"auth/**"} configurable (replace "auth/**" with ${dm.filterPattern})
Problem: in #RequestMapping ${dm.filterPattern} isn't resolved, although #PropertySource is processed.
This is the entry dm.filterPattern in dmConfig.properties:
dm.filterPattern=/auth/*
Here is some essential code, with all Spring annotations.
Controller:
The output of the method init() shows me that #PropertySource is processed correctly. env.getProperty("...") returns correct values.
#Controller
#PropertySource("classpath:/dmConfig.properties")
#RequestMapping(value ={ "${dm.filterPattern}"})
public class DmProxyController implements ApplicationContextAware
{
private Environment env;
#Autowired
public DmProxyController(Environment env)
{
this.env = env;
}
#RequestMapping(path={"${dm.filterPattern}"} ,method = RequestMethod.POST)
protected void doPost(HttpServletRequest customerRequest, HttpServletResponse response)
throws ServletException, IOException, DmException
{
// code for POST request
}
#RequestMapping(path={"${dm.filterPattern}"} ,method = RequestMethod.GET)
protected void doGet(HttpServletRequest customerRequest, HttpServletResponse response)
throws ServletException, IOException, DmException
{
// code for GET request
}
#PostConstruct
public void init() throws ServletException
{
RequestMappingHandlerMapping requestMapping=
(RequestMappingHandlerMapping) appContext.getBean("requestMappingHandlerMapping");
Map<RequestMappingInfo, HandlerMethod> handlerMethods = requestMapping.getHandlerMethods();
logger.debug("RequestMapping via dm.filterPattern: {}",
env.getProperty("dm.filterPattern"));
logger.debug("Handler Methods: {}", handlerMethods.size());
for (RequestMappingInfo mapInfo : handlerMethods.keySet())
{
logger.debug(" Mappinginfo: {} --> {}", mapInfo, handlerMethods.get(mapInfo));
}
}
}
Class with bean definitions
#Configuration
#PropertySource("classpath:/dmConfig.properties")
#ComponentScan(basePackages = "com.dm.filter, com.dm.controller")
#EnableTransactionManagement(mode = AdviceMode.PROXY, proxyTargetClass = false)
#Import({DmSecurityConfigurer.class, DmWebConfigurer.class})
public class DmRoot
{
}
DispatcherServletInitializer
public class DmDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer
{
#Override
protected Class<?>[] getRootConfigClasses()
{ return new Class[]{DmRoot.class}; }
#Override
protected Class<?>[] getServletConfigClasses()
{ return null; }
#Override
protected String[] getServletMappings()
{ return new String[]{"/"}; }
#Override
protected String getServletName()
{ return "dmDispatcherServlet"; }
#Override
protected void customizeRegistration(ServletRegistration.Dynamic registration)
{
super.customizeRegistration(registration);
registration.setLoadOnStartup(1);
}
}
WebConfigurer
public class DmWebConfigurer extends WebMvcConfigurerAdapter
{
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
super.addResourceHandlers(registry);
registry.addResourceHandler("/index.html").addResourceLocations("/");
registry.setOrder(Integer.MAX_VALUE-5);
}
}
SecurityWebApplicationInitializer
public class DmSecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer
{
public DmSecurityWebApplicationInitializer()
{
// some logging
}
#Override
protected void beforeSpringSecurityFilterChain(ServletContext servletContext)
{ // adding own filters }
#Override
protected void afterSpringSecurityFilterChain(ServletContext servletContext)
{ // adding own filters }
}
SecurityConfigurer
#EnableWebMvc
#EnableWebSecurity
#PropertySource("classpath:dmConfig.properties")
public class DmSecurityConfigurer extends WebSecurityConfigurerAdapter
{
private static Logger logger = LogManager.getLogger(DmSecurityConfigurer.class.getName());
#Autowired
private Environment env;
#Autowired
private UserDetailsService dmUserDetailsService;
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception
{
String urlPattern = env.getProperty("dm.springSecurityPattern");
String realmName = env.getProperty("dm.springSecurityRealm");
httpSecurity.httpBasic().realmName(realmName)
.and().userDetailsService(dmUserDetailsService)
.authorizeRequests()
.antMatchers(urlPattern).authenticated()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.csrf().disable();
}
}
There is a possibility that PropertySourcesPlaceholderConfigurer is being initialised later in the spring context than your controller and hence the values are not resolved. try adding explicit bean definition for PropertySourcesPlaceholderConfigurer in one of the root configuration file as below;
#PropertySource("classpath:/dmConfig.properties")
public class DmWebConfigurer extends WebMvcConfigurerAdapter
{
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
super.addResourceHandlers(registry);
registry.addResourceHandler("/index.html").addResourceLocations("/");
registry.setOrder(Integer.MAX_VALUE-5);
}
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
The reason you can see the values properly in your init() method is because it is called after all the beans are initialised including PropertySourcesPlaceholderConfigurer.

Spring Security seems to be ignoring a certain service

I am trying to implement Method Security using #PreAuthorize.
Spring Version: 4.2.3.Release
Spring Security: 4.0.3.Release
I have implemented a CustomPermissionEvaluator. I have noticed that it seems to be working fine except for 1 service where the hasPmerission is not called.
I know this because I get the a logging message from hasPermission / or in the erroneous case do not get the log:
public boolean hasPermission(Authentication authentication, Object o, Object o1) {
logger.info("Call to hasPermission with "+o+" and "+o1);
...
}
My Spring configuration is as follows:
#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;
}
}
Method 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;
}
The Service in question:
#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());
}
}
And the controller from which i call the service layer:
#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();
}
When calling api/stakeholder/types" with method = POST
This is my debug output:
Add Stakeholder type in controller
Create stakeholder type in service layer
INSERT INTO prefix_http_www_ontorais_de_stakeholdertype(id,stakeholderName) VALUES(DEFAULT,'TESTEWRTERETE');
As you can see the log from hasPermission is not present -> not called.
I can see that the method is called from my other method sercurity annotations in other service objects.
A similar Service which correctly invokes hasPermission as expected just for comparison:
#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));
}
Any hints on what I am doing wrong/missing/am blind for are very welcome thanks.
Benedict
Ok I found the problem, and a solution.
The Problem was that my CustomPermissionEvaluator depended on a method within the StakeholderService. Even though that method was not secured this resulted in the Spring not being able to proxy the object, therefore preventing any security checks.
Even though it is a bad idea to use a service layer object in the PermissionEvaluator, perhaps someone could elaborate on the exact implications, as i am definately not an expert in spring sercurity

Categories

Resources