I am writing test to check the working of spring MVC interceptor.
I have my working controller for which i have introduced interceptor code.
Everything is working fine except interceptor is not being executed.
No error nothing.
Interceptor:
package com.neha.javabrains;
import java.util.Calendar;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
#Component
public class TimeBasedInterceptor extends HandlerInterceptorAdapter{
private int openingTime=9;
private int closingTime=18;
public int getOpeningTime() {
return openingTime;
}
public void setOpeningTime(int openingTime) {
this.openingTime = openingTime;
}
public int getClosingTime() {
return closingTime;
}
public void setClosingTime(int closingTime) {
this.closingTime = closingTime;
}
public boolean preHandle(HttpServletRequest httpRequest,HttpServletResponse httpResponse) throws Exception
{
System.out.println("here in interceptor");
Calendar cal=Calendar.getInstance();
int hour=cal.HOUR_OF_DAY;
if(openingTime<=hour && hour<closingTime)
{
return true;
}
httpResponse.sendRedirect("http://localhost:8080/SpringWebProject/outsideHours.html");
return false;
}
}
Application Context entry:
<context:component-scan base-package="com.neha.javabrains" />
<context:annotation-config/>
<mvc:annotation-driven />
<mvc:default-servlet-handler />
<mvc:resources mapping="/resources/**" location="/resources/" />
<tx:annotation-driven transaction-manager="txManager"/>
<aop:aspectj-autoproxy />
<mvc:interceptors>
<bean class="com.neha.javabrains.TimeBasedInterceptor">
</bean>
</mvc:interceptors>
Controller:
package com.neha.javabrains;
import java.util.Locale;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.context.MessageSource;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Validator;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
#Controller
public class LoginController {
public LoginService loginService;
#Autowired
#Qualifier("loginFormValidator")
public Validator validator;
#Autowired
public MessageSource messageSource;
#InitBinder
private void initBinder(WebDataBinder binder) {
binder.setValidator(validator);
}
#Autowired
private Environment environment;
#RequestMapping("/")
public String doLogin(ModelMap modelMap)
{
System.out.println("doLogin" +loginService);
String message=messageSource.getMessage("message", null, "default", Locale.UK);
System.out.println("Message is:" + message);
LoginForm loginForm=new LoginForm();
modelMap.put("loginForm",loginForm);
return "login";
}
public void printData()
{
System.out.println("just to test aspect programming");
}
#RequestMapping("/login")
public String verifyLogin(#Valid #ModelAttribute("loginForm") LoginForm loginForm,BindingResult bindingResult)
{
if(bindingResult.hasErrors())
{
System.out.println("here in error" + bindingResult.getAllErrors().get(0));
return "login";
}
loginService.verifyLogin(loginForm);
LoginForm loginFrm=new LoginForm();
loginFrm.setUsername(loginForm.getUsername());
loginFrm.setPassword(loginForm.getPassword());
ModelAndView mav=new ModelAndView();
mav.addObject("loginForm", loginFrm);
return "result";
}
#RequestMapping("/addUser")
public String addUser(#ModelAttribute("LoginForm") LoginForm loginForm,LoginForm loginFrm)
{
System.out.println("In add User");
loginService.addUser(loginForm);
loginFrm.setUsername(loginForm.getUsername());
loginFrm.setPassword(loginForm.getPassword());
ModelAndView mav=new ModelAndView();
mav.addObject("LoginForm", loginFrm);
return "result";
}
public LoginService getLoginService() {
return loginService;
}
#Autowired
#Required
public void setLoginService(LoginService loginService) {
this.loginService = loginService;
System.out.println("i was called" + loginService);
}
public Environment getEnvironment() {
return environment;
}
public void setEnvironment(Environment environment) {
this.environment = environment;
}
public MessageSource getMessageSource() {
return messageSource;
}
public void setMessageSource(MessageSource messageSource) {
this.messageSource = messageSource;
}
}
Web.xml entry is:
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>Neha</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext*.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Neha</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>spring.profiles.active</param-name>
<param-value>dev</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
</web-app>
Can anyone please help.....
You seem to have missed the path where you want to apply the interceptor.
Try this
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" /> <!-- Specify here what all path you want to intercept -->
<bean class="com.neha.javabrains.TimeBasedInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
Hope this helps.
Related
I got this error after making some changes to my appconfig-security.xml file
appconfig-security.xml
`
<http auto-config="true">
<intercept-url pattern="/" access="hasAnyRole('ROLE_ADMIN','ROLE_INSTRUCTOR','ROLE_MEMBER')"/>
<intercept-url pattern="/welcome" access="hasAnyRole('ROLE_ADMIN','ROLE_INSTRUCTOR')"/>
<intercept-url pattern="/profile" access="hasRole('ROLE_MEMBER')"/>
<form-login login-page="/login" default-target-url="/welcome" authentication-failure-url="/login?error" username-parameter="username" password-parameter="password"/>
<logout logout-success-url="/login?logout" />
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="userDetailsServiceImpl">
<password-encoder ref="encoder"></password-encoder>
</authentication-provider>
</authentication-manager>
<beans:bean id="userDetailsServiceImpl" class="com.trygym.solution.service.UserDetailsServiceImpl"></beans:bean>
<beans:bean id="encoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
<beans:constructor-arg name="strength" value="11"/>
</beans:bean>
`
Before I had only one role in the database. Then I tried to do some security check and allocate access to users. Then I ended up with that error. I didn't make any changes to web.xml.
web.xml
`
<display-name>Gym Related Web Application</display-name>
<!-- Location of Java #Configuration classes that configure the components that makeup this application -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/appconfig-root.xml</param-value>
</context-param>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
`
I am using spring hibernate. Please can anyone help me to find where it might be the error locate. Thanks.
HomeController
package com.trygym.solution.web;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
#Controller
class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
/**
* Simply selects the home view to render by returning its name.
*/
#RequestMapping(value = "/", method = RequestMethod.GET)
private String home(Locale locale, Model model) {
logger.info("Welcome home! The client locale is {}.", locale);
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate );
return "home";
}
}
UserController
package com.trygym.solution.web;
import com.trygym.solution.model.User;
import com.trygym.solution.service.SecurityService;
import com.trygym.solution.service.UserService;
import com.trygym.solution.validator.UserValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
#Controller
public class UserController {
#Autowired
private UserService userService;
#Autowired
private SecurityService securityService;
#Autowired
private UserValidator userValidator;
#RequestMapping(value = "/forget_password", method = RequestMethod.POST)
public String forget_password(Model model) {
//model.addAttribute("userForm", new User());
return "forget_password";
}
#RequestMapping(value = "/registration", method = RequestMethod.GET)
public String registration(Model model) {
model.addAttribute("userForm", new User());
return "registration";
}
#RequestMapping(value = "/registration", method = RequestMethod.POST)
public String registration(#ModelAttribute("userForm") User userForm, BindingResult bindingResult, Model model) {
userValidator.validate(userForm, bindingResult);
if (bindingResult.hasErrors()) {
return "registration";
}
userService.save(userForm);
securityService.autologin(userForm.getUsername(), userForm.getPasswordConfirm());
return "redirect:/welcome";
}
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String login(Model model, String error, String logout) {
if (error != null)
model.addAttribute("error", "Your username and password is invalid.");
if (logout != null)
model.addAttribute("message", "You have been logged out successfully.");
return "login";
}
#RequestMapping(value = {"/", "/welcome"}, method = RequestMethod.GET)
public String welcome(Model model) {
return "welcome";
}
}
The problem here is that both HomeController.home and UserController.welcome are both mapped to / and Spring can't determine which method to call when the endpoint is accessed. Removing the mapping from one method resolves this particular issue.
When I try to go to link http://localhost:8080/ I get "HTTP Status 404", I use Tomcat 7.0.47, and I get the following error : The requested resource is not available.
WebConfig.Java
package config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
#EnableWebMvc
#Configuration
#ComponentScan
public class WebConfig extends WebMvcConfigurerAdapter{
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/static/js/**")
.addResourceLocations("/resources/static/js/");
registry.addResourceHandler("/resources/static/css/**")
.addResourceLocations("/resources/static/css/");
registry.addResourceHandler("/resources/static/views/**")
.addResourceLocations("/resources/static/views/");
registry.addResourceHandler("/resources/static/**")
.addResourceLocations("/resources/static/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("/webjars/");
}
#Bean
public ViewResolver getViewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/jsp/");
resolver.setSuffix(".jsp");
return resolver;
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
WebAppInitalizer.Java
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
public class WebAppInitializer implements WebApplicationInitializer {
private static final String CONFIG_LOCATION = "config";
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
System.out.println("***** Initializing Application for " + servletContext.getServerInfo() + " *****");
// Create ApplicationContext
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
applicationContext.setConfigLocation(CONFIG_LOCATION);
// Add the servlet mapping manually and make it initialize automatically
DispatcherServlet dispatcherServlet = new DispatcherServlet(applicationContext);
ServletRegistration.Dynamic servlet = servletContext.addServlet("mvc-dispatcher", dispatcherServlet);
servlet.addMapping("/");
servlet.setAsyncSupported(true);
servlet.setLoadOnStartup(1);
}
}
MainController.Java
package controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
#Controller
public class MainController {
#RequestMapping("/")
public String homepage(){
return "homepage";
}
}
My project has the following structure :
try to add this #AnnotationDrivenConfig on top of WebConfig and change this #ComponentScan with this #ComponentScan("controller")
Try to add some text into your requestMapping example:
#RequestMapping("/homePage")
and then go to http://localhost:8080/homePage
Hi I am new to Spring Security and Spring Oauth, i am configuring a Spring Oauth Server and Resource Server java based. but i need to configure some of the web mvc based on xml, like need to initialize servlet parameters.
below is my Web.xml
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Spring Web MVC Application</display-name>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Spring Security -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>contextAttribute</param-name>
<param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.dispatcher</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
and mvc-dispatcher-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:component-scan base-package="com.resource" />
<mvc:annotation-driven />
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/userbase" />
<property name="username" value="username" />
<property name="password" value="password" />
</bean>
</beans>
and Error log is below:
HTTP Status 500 - No WebApplicationContext found: no ContextLoaderListener registered?
type Exception report
message No WebApplicationContext found: no ContextLoaderListener registered?
description The server encountered an internal error that prevented it from fulfilling this request.
exception
java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:252)
note The full stack trace of the root cause is available in the Apache Tomcat/7.0.68 logs.
Apache Tomcat/7.0.68
SecurityConfiguration.java
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
DataSource dataSource;
private BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
#Autowired
public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource).passwordEncoder(passwordEncoder)
.usersByUsernameQuery(
"select username,password, enabled from users where username=?")
.authoritiesByUsernameQuery(
"select username, authority from authorities where username=?");
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
****OAuth2ServerConfig.java****
import java.security.Principal;
import java.util.UUID;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
import org.springframework.web.bind.annotation.RequestMapping;
#Configuration
public class OAuth2ServerConfig {
#Configuration
#EnableResourceServer
protected static class ResourceServer extends ResourceServerConfigurerAdapter {
#Autowired
private DataSource dataSource;
public static final String RESOURCE_ID = "resource_id";
#Bean
public JdbcTokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
#Bean
protected AuthorizationCodeServices authorizationCodeServices() {
return new JdbcAuthorizationCodeServices(dataSource);
}
#Override
public void configure(ResourceServerSecurityConfigurer resources)
throws Exception {
resources.tokenStore(tokenStore());
resources.resourceId(RESOURCE_ID);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated();
}
}
#RequestMapping("/")
public String getInfo() {
return "id: " + UUID.randomUUID() + " content : Spring Oauth2 Welcome first Page";
}
#RequestMapping("/user")
public Principal getUser(Principal principal) {
return principal;
}
}
Please help me on above.
It looks like contextAttribute suffix of the springSecurityFilterChain must match the dispatcher servlet name. Here in your case i see the contextAttribute suffix is dispatcher but the dispatcher servlet name is mvc-dispatcher. Can you try matching them i.e change the contextAttibute suffix to mvc-dispatcher as below and see if the issue goes away.
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>contextAttribute</param-name>
<param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.mvc-dispatcher</param-value>
</init-param>
</filter>
I got this info from https://www.txedo.com/blog/spring-security-no-contextloaderlistener-registered/
I'm not 100% sure I'm performing the correct request but I can't seem to get a token for a client. I've based my solution off of this tutorial 5 minutes with spring oauth 2.0.
I'm performing this request from postman:
/oauth/token?grant_type=client_credentials&client_id=mysupplycompany&client_secret=mycompanyk
That request responds with an exception:
org.springframework.security.authentication.InsufficientAuthenticationException:
There is no client authentication. Try adding an appropriate
authentication filter.
org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(TokenEndpoint.java:91)
Below are some files/classes you may need to help me figure out any issues.
WebInitializer
package com.squirrels.config;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration.Dynamic;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.DelegatingFilterProxy;
import org.springframework.web.servlet.DispatcherServlet;
public class WebInitializer implements WebApplicationInitializer {
public void onStartup(ServletContext servletContext) throws ServletException {
WebApplicationContext context = getContext();
servletContext.addListener(new ContextLoaderListener(context));
servletContext.addListener(new RequestContextListener());
Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
servlet.addMapping("/");
servlet.setLoadOnStartup(1);
DelegatingFilterProxy filter = new DelegatingFilterProxy("springSecurityFilterChain");
filter.setContextAttribute("org.springframework.web.servlet.FrameworkServlet.CONTEXT.dispatcher");
servletContext.addFilter("springSecurityFilterChain", filter).addMappingForUrlPatterns(null, false, "/*");
}
private AnnotationConfigWebApplicationContext getContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setConfigLocation("com.squirrels.config");
return context;
}
}
PersistenceJPAConfig
package com.squirrels.config;
import java.util.Properties;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import liquibase.integration.spring.SpringLiquibase;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#Configuration
#EnableTransactionManagement
#ComponentScan({ "com.squirrels.controller", "com.squirrels.services", "com.squirrels.persistence.dao", "com.squirrels.auth" })
#PropertySource(value = { "classpath:squirrel.properties" })
#ImportResource("classpath:spring-security.xml")
public class PersistenceJPAConfig {
#Autowired
private Environment environment;
#Bean
public SpringLiquibase liquibase() {
SpringLiquibase liquibase = new SpringLiquibase();
liquibase.setDataSource(dataSource());
liquibase.setDefaultSchema(environment.getRequiredProperty("db_schema"));
liquibase.setChangeLog("classpath:/db/changelog/db.changelog-master.xml");
return liquibase;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPersistenceUnitName("SquirrelAuth");
em.setPackagesToScan(new String[] { "com.squirrels.persistence.model" });
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
}
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(environment.getRequiredProperty("db_driverClass"));
dataSource.setUrl(environment.getRequiredProperty("db_jdbcUrl"));
dataSource.setUsername(environment.getRequiredProperty("db_user"));
dataSource.setPassword(environment.getRequiredProperty("db_password"));
return dataSource;
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
Properties additionalProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.dialect", environment.getRequiredProperty("db_hibernateDialect"));
return properties;
}
}
security-spring.xml
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns:sec="http://www.springframework.org/schema/security" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd">
<sec:http pattern="/oauth/token" create-session="stateless"
authentication-manager-ref="authenticationManager">
<sec:intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<sec:anonymous enabled="false" />
<sec:http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<sec:custom-filter ref="clientCredentialsTokenEndpointFilter"
before="BASIC_AUTH_FILTER" />
<sec:access-denied-handler ref="oauthAccessDeniedHandler" />
</sec:http>
<sec:http pattern="/api/**" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint">
<sec:anonymous enabled="false" />
<sec:intercept-url pattern="/api/**" method="GET"
access="IS_AUTHENTICATED_FULLY" />
<sec:custom-filter ref="resourceServerFilter"
before="PRE_AUTH_FILTER" />
<sec:access-denied-handler ref="oauthAccessDeniedHandler" />
</sec:http>
<bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
</bean>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="springsec/client" />
<property name="typeName" value="Basic" />
</bean>
<bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler">
</bean>
<bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider
user-service-ref="clientDetailsUserService" />
</sec:authentication-manager>
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
<bean id="clientDetails" class="com.squirrels.auth.OAuthClientDetailsImpl">
<property name="id" value="mysupplycompany" />
<property name="secretKey" value="mycompanykey" />
</bean>
<sec:authentication-manager id="userAuthenticationManager">
<sec:authentication-provider ref="customUserAuthenticationProvider" />
</sec:authentication-manager>
<bean id="customUserAuthenticationProvider" class="com.squirrels.auth.OAuthAuthenticationProvider">
</bean>
<oauth:authorization-server
client-details-service-ref="clientDetails" token-services-ref="tokenServices">
<oauth:authorization-code />
<oauth:implicit />
<oauth:refresh-token />
<oauth:client-credentials />
<oauth:password authentication-manager-ref="userAuthenticationManager" />
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter"
resource-id="springsec" token-services-ref="tokenServices" />
<bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore" />
<bean id="tokenServices"
class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="supportRefreshToken" value="true" />
<property name="accessTokenValiditySeconds" value="120"></property>
<property name="clientDetailsService" ref="clientDetails" />
</bean>
<mvc:annotation-driven />
</beans>
OAuthAuthenticationProvider
package com.squirrels.auth;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
public class OAuthAuthenticationProvider implements AuthenticationProvider {
#Autowired
private OAuthProxy proxy;
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
boolean result = proxy.isValidUser("1", authentication.getPrincipal().toString(), authentication.getCredentials().toString());
if (result) {
List<GrantedAuthority> grantedAuthorities =
new ArrayList<GrantedAuthority>();
OAuthAuthenticationToken auth = new OAuthAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(), grantedAuthorities);
return auth;
} else {
throw new BadCredentialsException("Bad User Credentials.");
}
}
#Override
public boolean supports(Class<?> arg0) {
return true;
}
}
WebMvcConfig
package com.squirrels.config;
import java.util.ArrayList;
import java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.ContentNegotiatingViewResolver;
#Configuration
#EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
};
/*
* Configure ContentNegotiatingViewResolver
*/
#Bean
public ViewResolver contentNegotiatingViewResolver(ContentNegotiationManager manager) {
ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
resolver.setContentNegotiationManager(manager);
// Define all possible view resolvers
List<ViewResolver> resolvers = new ArrayList<ViewResolver>();
resolvers.add(jsonViewResolver());
resolver.setViewResolvers(resolvers);
return resolver;
}
/*
* Configure View resolver to provide JSON output using JACKSON library to
* convert object in JSON format.
*/
#Bean
public ViewResolver jsonViewResolver() {
return new JsonViewResolver();
}
}
OAuthenticationToken
package com.squirrels.auth;
import java.util.Collection;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
public class OAuthAuthenticationToken extends AbstractAuthenticationToken {
private static final long serialVersionUID = -1092219614309982278L;
private final Object principal;
private Object credentials;
public OAuthAuthenticationToken(Object principal, Object credentials,
Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;
this.credentials = credentials;
super.setAuthenticated(true);
}
#Override
public Object getCredentials() {
return credentials;
}
#Override
public Object getPrincipal() {
return principal;
}
}
OAuthClientDetailsImpl
package com.squirrels.auth;
import java.util.ArrayList;
import java.util.List;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.ClientRegistrationException;
import org.springframework.security.oauth2.provider.NoSuchClientException;
import org.springframework.security.oauth2.provider.client.BaseClientDetails;
public class OAuthClientDetailsImpl implements ClientDetailsService {
private String id;
private String secretKey;
#Override
public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {
if (clientId.equals(id))
{
List<String> authorizedGrantTypes = new ArrayList<String>();
authorizedGrantTypes.add("password");
authorizedGrantTypes.add("refresh_token");
authorizedGrantTypes.add("client_credentials");
BaseClientDetails clientDetails = new BaseClientDetails();
clientDetails.setClientId(id);
clientDetails.setClientSecret(secretKey);
clientDetails.setAuthorizedGrantTypes(authorizedGrantTypes);
return clientDetails;
}
else {
throw new NoSuchClientException("No client recognized with id: " + clientId);
}
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getSecretKey() {
return secretKey;
}
public void setSecretKey(String secretKey) {
this.secretKey = secretKey;
}
}
OAuthProxy
package com.squirrels.auth;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.squirrels.dto.UserDTO;
import com.squirrels.persistence.dao.UserDao;
import com.squirrels.persistence.model.UserModel;
import com.squirrels.services.UserUtil;
#Service
public class OAuthProxy {
protected static final Logger logger = LogManager.getLogger(OAuthProxy.class);
#Autowired
private UserDao userDaoImpl;
#Autowired
private UserUtil userUtil;
#Transactional
public boolean isValidUser(String organizationId, String username, String password) {
try{
UserModel user = userDaoImpl.findByOrganizationAndUserName(organizationId, username);
UserDTO userDto = userUtil.getDTO(user);
//TODO validate password (or other means of auth)
return true;
}catch(Exception e){
logger.error("No user: " + username + " found in organization: " + organizationId, e);
}
return false;
}
}
I had the same problem.
In my case is was because I mapped my DispatcherServlet like this :
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/dispatcher/*</url-pattern>
</servlet-mapping>
This was causing problem because security was configured on "/oauth/token", instead of "/dispatcher/oauth/token" :
<security:http pattern="/oauth/token" ...
So I just had to do :
<security:http pattern="/dispatcher/oauth/token"
And the problem was gone.
If that is not the case for you, it may be because you have no DelegatingFilterProxy configured.
Try configuring it in web.xml :
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
And if you use java config instead of web.xml, extending the class org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer
will configure it.
I I am trying to use spring security to control authentication in my RMI client app.
I am using maven to load 3.1.3.RELEASE spring
Then in my client xml, I am seeing "authentication-provider is not allowed here" message.
This is the spring xml file:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd
">
<bean id="employeeService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl" value="rmi://localhost:1234/employee-service"/>
<property name="serviceInterface" value="rmi.common.EmployeeService"/>
<property name="refreshStubOnConnectFailure"><value>true</value></property>
<property name="remoteInvocationFactory"><ref bean="remoteInvocationFactory"/></property>
</bean>
<bean id="remoteInvocationFactory" class="org.springframework.security.remoting.rmi.ContextPropagatingRemoteInvocationFactory"/>
<security:authentication-manager alias="authManager">
<security:authentication-provider ref="customAuthenticationProvider"/>
</security:authentication-manager>
<bean id="customAuthenticationProvider" class="rmi.authentication.CustomAuthenticationProvider"/>
</beans>
This is my client side code:
package rmi.client;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import rmi.common.Employee;
import rmi.common.EmployeeService;
import javax.annotation.Resource;
import java.util.Iterator;
import java.util.List;
public class EmployeeClient {
#Resource(name = "authManager")
private org.springframework.security.authentication.AuthenticationManager authenticationManager; // specific for Spring Security
private static ApplicationContext ctx;
public static void main(String[] args) {
ctx = new ClassPathXmlApplicationContext("rmi-client-context.xml");
new EmployeeClient().exec();
}
public void exec() {
EmployeeService employee = (EmployeeService) ctx.getBean("employeeService");
Authentication authenticate = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken("myuser", "mypwd"));
if (authenticate.isAuthenticated()) {
SecurityContextHolder.getContext().setAuthentication(authenticate);
}
employee.addEmployee(new Employee("Jack Su", "address1"));
employee.addEmployee(new Employee("Alice Liu", "address2"));
List<Employee> employees = employee.getEmployees();
System.out.println("Total number of employees: " + employees.size());
Iterator<Employee> it = employees.iterator();
while (it.hasNext()) {
Employee emp = (Employee) it.next();
System.out.println(" " + emp);
}
}
}
This is my testing authentication provider:
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import java.util.ArrayList;
import java.util.List;
#Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
#Override
public Authentication authenticate(Authentication argAuth) throws AuthenticationException {
List<GrantedAuthority> grantedAuths = new ArrayList<GrantedAuthority>();
grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
Authentication auth = new UsernamePasswordAuthenticationToken(argAuth.getPrincipal(),
argAuth.getCredentials(), grantedAuths);
auth.setAuthenticated(true);
return auth;
}
#Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
Not sure about your exact error, but something in your configuration might be wrong.
Your EmployeeClient is not a Spring-Managed-Bean, because you created it with new-operator, so your #Resource(name = "authManager") should not work. If you posted all your configuration authenticationManager.authenticate(..) should produce NullPointerException.
Instead of new you could do this in your Main.
EmployeeClient client = (EmployeeClient) ctx.getBean("employeeClient");
client.exec();
(and add #Service to your EmployeeClient).