Spring Security Request method 'POST' not supported - spring

The page having status 405 and also authentication is not working.
Error from Spring Boot log
o.s.web.servlet.PageNotFound : Request method 'POST' not supported
Error from jsp page:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
There was an unexpected error (type=Method Not Allowed, status=405).
Request method 'POST' not supported
Spring Info:
- Using Spring Security 3.2.5
- Using Spring Boot App to start up server.
- Spring-Java-Config
Codes:
SecurityConfig.java
#EnableAutoConfiguration
#ComponentScan(basePackages = { "org.myakasha.crm","org.myakasha.crm.controller","org.myakasha.crm.model"})
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Autowired
DataSource dataSource;
#Autowired
public void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("select username,password, enabled from users where username=?")
.authoritiesByUsernameQuery("select username, role from user_roles where username=?");
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
.and()
.formLogin().loginPage("/login").failureUrl("/login?error").usernameParameter("username").passwordParameter("password")
.and()
.logout().logoutSuccessUrl("/login?logout")
.and()
.exceptionHandling().accessDeniedPage("/403")
.and()
.csrf();
}
}
SecurityController.java
#Controller
public class SecurityController {
#RequestMapping(value = { "/welcome**" }, method = RequestMethod.GET)
public ModelAndView defaultPage() {
ModelAndView model = new ModelAndView();
model.addObject("title", "Spring Security + Hibernate Example");
model.addObject("message", "This is default page!");
model.setViewName("hello");
return model;
}
#RequestMapping(value = "/admin**", method = RequestMethod.GET)
public ModelAndView adminPage() {
ModelAndView model = new ModelAndView();
model.addObject("title", "Spring Security + Hibernate Example");
model.addObject("message", "This page is for ROLE_ADMIN only!");
model.setViewName("admin");
return model;
}
#RequestMapping(value = "/login", method = {RequestMethod.GET} )
public ModelAndView login(#RequestParam(value = "error", required = false) String error,
#RequestParam(value = "logout", required = false) String logout, HttpServletRequest request) {
ModelAndView model = new ModelAndView();
if (error != null) {
model.addObject("error", getErrorMessage(request, "SPRING_SECURITY_LAST_EXCEPTION"));
}
if (logout != null) {
model.addObject("msg", "You've been logged out successfully.");
}
model.setViewName("login");
return model;
}
// customize the error message
private String getErrorMessage(HttpServletRequest request, String key) {
Exception exception = (Exception) request.getSession().getAttribute(key);
String error = "";
if (exception instanceof BadCredentialsException) {
error = "Invalid username and password!";
} else if (exception instanceof LockedException) {
error = exception.getMessage();
} else {
error = "Invalid username and password!";
}
return error;
}
// for 403 access denied page
#RequestMapping(value = "/403", method = RequestMethod.GET)
public ModelAndView accesssDenied() {
ModelAndView model = new ModelAndView();
// check if user is login
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (!(auth instanceof AnonymousAuthenticationToken)) {
UserDetails userDetail = (UserDetails) auth.getPrincipal();
System.out.println(userDetail);
model.addObject("username", userDetail.getUsername());
}
model.setViewName("403");
return model;
}
}
WebConfig.java
#EnableAutoConfiguration
#EnableWebMvc
#ComponentScan(basePackages = {"org.myakasha.crm","org.myakasha.crm.controller","org.myakasha.crm.model"})
public class WebConfig extends WebMvcConfigurerAdapter{
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
/**
* This function to replace servlet-content.xml
* Resolves views selected for rendering by #Controllers to .jsp resources in the /WEB-INF/views directory
**/
#Bean
public InternalResourceViewResolver getInternalResourceViewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver .setPrefix("/WEB-INF/views/");
viewResolver .setSuffix(".jsp");
return viewResolver ;
}
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasenames("classpath:message");
messageSource.setUseCodeAsDefaultMessage(true);
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
}
PersistenceConfig.java
#Configuration
#EnableTransactionManagement
#PropertySource({ "classpath:persistence-mysql.properties" })
#ComponentScan({ "org.myakasha.crm" })
public class PersistenceConfig {
#Autowired
private Environment env;
public PersistenceConfig() {
super();
}
#Bean
public LocalSessionFactoryBean sessionFactory() {
final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(restDataSource());
sessionFactory.setPackagesToScan(new String[] { "org.myakasha.crm.model" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public DataSource restDataSource() {
final BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName")));
dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url")));
dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user")));
dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass")));
return dataSource;
}
#Bean
#Autowired
public HibernateTransactionManager transactionManager(final SessionFactory sessionFactory) {
final HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory);
return txManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
final Properties hibernateProperties() {
final Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
hibernateProperties.setProperty("hibernate.show_sql", "true");
// hibernateProperties.setProperty("hibernate.format_sql", "true");
// hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true");
return hibernateProperties;
}
}

try to add login-processing-url to the SecurityConfig
in XML it looks like this
<form-login
login-page="/login"
<!-- for <form method="post" action="/login-process"> -->
login-processing-url="/login_process"
default-target-url="/home"
authentication-failure-url="/login?error"
username-parameter="username"
password-parameter="password" />

it seems to be that you have enabled the CSRF. can you check whether you are passing the CSRF token, in the form. if not please add the following line to your form.
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>

Related

Spring social Facebook doesn't work in version 2.0.2

Hello everyone when I upgrade my application to spring version 2.0.2 I get this exception:
Description: Field connectionFactoryLocator in com.ssp.api.v1.security.SecurityConfiguration required a bean of type 'org.springframework.social.connect.ConnectionFactoryLocator' that could not be found.
here's my code:
SecurityConfiguration.java Configuration
#Configuration
#ComponentScan(basePackages = { "com.ssp.api.vi.security" })
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired private ConnectionFactoryLocator connectionFactoryLocator;
#Autowired private UsersConnectionRepository usersConnectionRepository;
#Autowired private FacebookConnectionSignup facebookConnectionSignup;
#Autowired private SspUserDetailsService sspUserDetailsService;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/api/session").permitAll()
.antMatchers("/h2-console/**").permitAll()
.antMatchers("/api/**").authenticated()
.and()
.requestCache()
.requestCache(new NullRequestCache())
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and().csrf().disable();
}
//#Autowired
#Bean
public ProviderSignInController providerSignInController() {
((InMemoryUsersConnectionRepository) usersConnectionRepository)
.setConnectionSignUp(facebookConnectionSignup);
return new ProviderSignInController(
connectionFactoryLocator,
usersConnectionRepository,
new FacebookSignInAdapter());
}
#Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.authenticationProvider(authenticationProvider());
}
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider
= new DaoAuthenticationProvider();
authProvider.setUserDetailsService(sspUserDetailsService);
authProvider.setPasswordEncoder(encoder());
return authProvider;
}
#Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder(11);
}
#Override
#Bean(name = BeanIds.AUTHENTICATION_MANAGER)
public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); }
#Override
#Bean(name = BeanIds.USER_DETAILS_SERVICE)
public UserDetailsService userDetailsServiceBean() throws Exception { return this.sspUserDetailsService; }
AuthUtil.java Class
protected static final Logger log = LoggerFactory.getLogger(AuthUtil.class);
public static void authenticate(Connection<?> connection) {
UserProfile userProfile = connection.fetchUserProfile();
String username = userProfile.getUsername();
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, null, null);
SecurityContextHolder.getContext().setAuthentication(authentication);
log.info("User {} {} connected.", userProfile.getFirstName(), userProfile.getLastName());
}
FacebookConnectionSignup.class Service
#Service
public class FacebookConnectionSignup implements ConnectionSignUp {
#Override
public String execute(Connection<?> connection) {
return connection.getDisplayName();
}
}
FacebookSignInAdapter.java Class
public class FacebookSignInAdapter implements SignInAdapter{
#Override
public String signIn(String userId, Connection<?> connection, NativeWebRequest request) {
SecurityContextHolder.getContext().setAuthentication(
new UsernamePasswordAuthenticationToken(
connection.getDisplayName(), null,
Arrays.asList(new SimpleGrantedAuthority("FACEBOOK_USER"))
)
);
return null;
}
}
SocialConfiguration.java Configuration
#Configuration
public class SocialConfiguration {
#Bean
public SignInAdapter authSignInAdapter() {
return (userId, connection, request) -> {
AuthUtil.authenticate(connection);
return null;
};
}
}
### SspUserDetailsService.class Service
#Service
public class SspUserDetailsService implements UserDetailsService {
#Autowired private UserRepository userRepository;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findById(username).orElse(null);
if (user == null)
throw new UsernameNotFoundException(username);
return new SspUserDetails(user);
}
}
Console Error:
Description:
Field connectionFactoryLocator in com.ssp.api.v1.security.SecurityConfiguration required a bean of type 'org.springframework.social.connect.ConnectionFactoryLocator' that could not be found.
Action:
Consider defining a bean of type 'org.springframework.social.connect.ConnectionFactoryLocator' in your configuration.
This code works perfectly In Spring 1.5.10 version.
How can I solve this issue?
Before of all thank you!
In Boot 2.x, you need to define the ConnectionFactoryLocator and UsersConnectionRepository in your SecurityConfiguration class, instead of autowiring them:
private ConnectionFactoryLocator connectionFactoryLocator() {
ConnectionFactoryRegistry registry = new ConnectionFactoryRegistry();
registry.addConnectionFactory(new FacebookConnectionFactory(appId, appSecret));
return registry;
}
private UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
return new InMemoryUsersConnectionRepository(connectionFactoryLocator);
}
Here, appId and appSecret are coming from application.properties.
You also need to change the implementation for your ProviderSignInController bean:
#Bean
public ProviderSignInController providerSignInController() {
ConnectionFactoryLocator connectionFactoryLocator = connectionFactoryLocator();
UsersConnectionRepository usersConnectionRepository = getUsersConnectionRepository(connectionFactoryLocator);
((InMemoryUsersConnectionRepository) usersConnectionRepository).setConnectionSignUp(facebookConnectionSignup);
return new ProviderSignInController(connectionFactoryLocator, usersConnectionRepository, new FacebookSignInAdapter());
}
You can find more details here.

spirng boot 2 jwt oauth2 + angular 5 can't get the JWT

I'm new working with spring boot and spring security and I'm trying to implement oauth2 to generate a JWT and used this token in an angular5 application, my situation is that after implementation I can get the token if a use postman or curl but when I use my web client in angular I can't get the token.
this is what I did.
My login method is angular
login(username: string, password: string ) {
const params: HttpParams = new HttpParams();
const headers: Headers = new Headers();
params.set('username', 'GDELOSSANTOS');
params.set('password', 'ADMIN');
params.set('client_id', 'ADMIN');
params.set('client_secret', 'ADMIN');
params.set('grant_type', 'password');
params.set('scope', '*');
headers.set('Content-Type', 'application/x-www-form-urlencoded');
return this.http.post(Constante.BACKEND_TOKEN_REQUEST, {headers}, {params} ).subscribe
(res => this.setSession);
}
My authorization server
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
private static final Logger logger = LogManager.getLogger(AuthorizationServerConfig.class);
#Value("${security.oauth2.resource.id}")
private String resourceId;
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Override
public void configure(final AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
#Override
public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
logger.traceEntry();
clients
.inMemory()
.withClient(ConstanteUtil.Seguridad.CLIEN_ID)
.secret(Seguridad.CLIENT_SECRET)
.authorizedGrantTypes(Seguridad.GRANT_TYPE_PASSWORD, Seguridad.AUTHORIZATION_CODE, Seguridad.REFRESH_TOKEN, Seguridad.IMPLICIT )
.authorities(UsusarioRoles.ROLE_ADMIN, UsusarioRoles.ROLE_USER)
.resourceIds(resourceId)
.scopes(Seguridad.SCOPE_READ, Seguridad.SCOPE_WRITE, Seguridad.TRUST)
.accessTokenValiditySeconds(Seguridad.ACCESS_TOKEN_VALIDITY_SECONDS).
refreshTokenValiditySeconds(Seguridad.FREFRESH_TOKEN_VALIDITY_SECONDS);
logger.info("Configuracion " + clients);
logger.traceExit();
}
#Bean
#Primary
public DefaultTokenServices tokenServices() {
final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
return defaultTokenServices;
}
#Override
public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
final TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer(), accessTokenConverter()));
endpoints.tokenStore(tokenStore())
.tokenEnhancer(tokenEnhancerChain)
.authenticationManager(authenticationManager);
}
#Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
final JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("123");
return converter;
}
#Bean
public TokenEnhancer tokenEnhancer() {
return new CustomTokenEnhancer();
}
}
My Resource Server
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
private static final Logger logger = LogManager.getLogger(AuthorizationServerConfig.class);
#Value("${security.oauth2.resource.id}")
private String resourceId;
#Override
public void configure(final HttpSecurity http) throws Exception {
logger.traceEntry("Entrada configure");
// #formatter:off
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.authorizeRequests().anyRequest().permitAll();
logger.info("Ejecucion de metodo " + http);
// #formatter:on
}
#Override
public void configure(final ResourceServerSecurityConfigurer config) {
config.resourceId(resourceId).stateless(true); }
}
The WebSecurity
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private static final Logger logger = LogManager.getLogger(WebSecurityConfig.class);
#Autowired
#Resource(name = "UsuarioService")
private UserDetailsService userDetailsService;
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Autowired
public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
logger.traceEntry("globalUserDetails", auth);
auth.userDetailsService(userDetailsService)
.passwordEncoder(encoder());
logger.traceExit("globalUserDetails", auth);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
logger.traceEntry();
logger.info("ejecutando configuracion " + http);
http.cors().disable()
.csrf().disable()
.anonymous().disable()
.authorizeRequests()
.antMatchers("/login", "/logout.do").permitAll()
.antMatchers("/**").authenticated()
.and().formLogin().loginPage("/login").permitAll()
.and().httpBasic();
logger.info("se ejecuto configuracion " + http);
}
#Bean
public BCryptPasswordEncoder encoder(){
return new BCryptPasswordEncoder();
}
#Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(0);
return bean;
}
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/auth/token").allowedOrigins("http://localhost:9000");
}
};
}
}
The implementation of loadUserDetail of UserDetailService
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
logger.traceEntry("Iniciando loadUserByUsername");
/Here we are using dummy data, you need to load user data from
database or other third party application/
try {
Usuario usuario = findAllUsuarioRoleByName(username);
logger.info("Se encontro el usaurio " + usuario);
UserBuilder builder = null;
if (usuario != null) {
List<String> roles = new ArrayList<>();
Collection<UsuarioRole> usuarioRoleByUsuarioName = usuarioRoleRepository.findAllUsuarioRoleByUsuarioName(usuario.getNombreUsuario());
logger.info("Roles encontrados " + usuarioRoleByUsuarioName.size());
for(UsuarioRole usuarioRole : usuarioRoleByUsuarioName) {
roles.add(usuarioRole.getRole().getNombreRole());
}
String[] rolesArray = new String[roles.size()];
rolesArray = roles.toArray(rolesArray);
builder = org.springframework.security.core.userdetails.User.withUsername(username);
builder.password(new BCryptPasswordEncoder().encode(usuario.getClaveUsuario()));
for (String string : rolesArray) {
logger.debug("**** " + string);
}
builder.roles(rolesArray);
} else {
throw new UsernameNotFoundException("User not found.");
}
return builder.build();
}finally {
logger.traceExit("Finalizando loadUserByUsername");
}
}
Make the following adjustments to your angular code.
Pass client_id and client_secret through Authorization header.
Serialize the object before post (you can reference this answer).
login(username: string, password: string ) {
let body = {
username: 'GDELOSSANTOS',
password: 'ADMIN',
grant_type: 'password'
};
// Serialize body object
let bodySerialized = 'grant_type=password&password=ADMIN&username=GDELOSSANTOS';
let headers = new HttpHeaders()
.set('Content-Type', 'application/x-www-form-urlencoded')
.set('Authorization', 'Basic ' + btoa("ADMIN:ADMIN"));
return this.http.post(Constante.BACKEND_TOKEN_REQUEST,
bodySerialized,
{
headers: headers
}).subscribe(res => this.setSession);
}

sessionRegistry.getAllPrincipals() is empty

I trying to get all logged-in users using sessionRegistry in my Spring-MVC application, i found a lot of posts and answers on how to resolve it, but i could not fix it. I'm using configuration by annotation.
I'm new to spring mvc and i want to learn a best practice, so all comments about other configurations or about my code are welcome.
Here is my code
#Configuration
#ComponentScan(basePackages = {"com.uno"})
#Import({ SecurityConfig.class })
#EnableWebMvc
public class AppConfig extends WebMvcConfigurerAdapter {
#Bean
public TilesViewResolver tilesViewResolver() {
TilesViewResolver resolver = new TilesViewResolver();
resolver.setViewClass(TilesView.class);
resolver.setOrder(1);
return resolver;
}
#Bean
public TilesConfigurer tilesConfigurer() {
TilesConfigurer tilesConfigurer = new TilesConfigurer();
tilesConfigurer.setCompleteAutoload(true);
tilesConfigurer.setCheckRefresh(true);
return tilesConfigurer;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations(
"/resources/");
}
#Bean
SessionFactory sessionFactory() {
org.hibernate.cfg.Configuration configuration = new org.hibernate.cfg.Configuration();
configuration.configure();
LocalSessionFactoryBuilder builder = new LocalSessionFactoryBuilder(
dataSource());
builder.scanPackages("com.uno.domain").addProperties(
configuration.getProperties());
return builder.buildSessionFactory();
}
#Bean
public DriverManagerDataSource dataSource() {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/uno");
ds.setUsername("root");
return ds;
}
#Bean
public HibernateTransactionManager transactionManager() {
return new HibernateTransactionManager(sessionFactory());
}
#Bean
UserDao userDao() {
return new UserDaoImpl();
}
#Bean
UserService userService() {
return new UserServiceImpl();
}
#Bean
RoleDao roleDao() {
return new RoleDaoImpl();
}
#Bean
RoleService roleService() {
return new RoleServiceImpl();
}
#Bean
ConnexionSucessHandler connexionSuccessHandler() {
return new ConnexionSucessHandler();
}
#Bean
PersistentTokenRepository remmeberMeTokenRepository() {
JdbcTokenRepositoryImpl db = new JdbcTokenRepositoryImpl();
db.setDataSource(dataSource());
return db;
}
/* Localization section */
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
#Bean
LocaleResolver localeResolver() {
SessionLocaleResolver sessionLocaleResolver = new SessionLocaleResolver();
sessionLocaleResolver.setDefaultLocale(new Locale("en"));
return sessionLocaleResolver;
}
#Bean
LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("lang");
return localeChangeInterceptor;
}
#Bean
ControllerClassNameHandlerMapping controllerClassNameHandlerMapping() {
ControllerClassNameHandlerMapping controllerClassNameHandlerMapping = new ControllerClassNameHandlerMapping();
Object[] interceptors = new Object[] { localeChangeInterceptor() };
controllerClassNameHandlerMapping.setInterceptors(interceptors);
return controllerClassNameHandlerMapping;
}
#Bean
ReloadableResourceBundleMessageSource messageSource() {
ReloadableResourceBundleMessageSource reloadableResourceBundleMessageSource = new ReloadableResourceBundleMessageSource();
reloadableResourceBundleMessageSource.setBasename("resources/i18n/messages");
reloadableResourceBundleMessageSource.setDefaultEncoding("UTF-8");
return reloadableResourceBundleMessageSource;
}
/* Localization section */
#Bean
CommonsMultipartResolver filterMultipartResolver(){
return new CommonsMultipartResolver();
}
}
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
#Qualifier("userService")
UserService userDetailsService;
#Autowired
ConnexionSucessHandler connexionSucessHandler;
#Autowired
SessionRegistry sessionRegistry;
#Autowired
PersistentTokenRepository remmeberMeTokenRepository;
#Autowired
ConcurrentSessionControlAuthenticationStrategy concurrentSessionControlAuthenticationStrategy;
#Autowired
ConcurrentSessionFilter concurrentSessionFilter;
#Autowired
RegisterSessionAuthenticationStrategy registerSessionAuthenticationStrategy;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/admin/**").hasRole("ADMIN").antMatchers("/mailManagement/**")
.hasAnyRole("USER", "ADMIN").antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
.antMatchers("/login/**").permitAll().and().formLogin().successHandler(connexionSucessHandler)
.loginPage("/login").failureUrl("/login?error").usernameParameter("username")
.passwordParameter("password").and().logout().invalidateHttpSession(true).deleteCookies("JSESSIONID")
.logoutUrl("/logout").logoutSuccessUrl("/login?logout").and().csrf().and().exceptionHandling()
.accessDeniedPage("/403").and().rememberMe().rememberMeParameter("uno-remember-me")
.rememberMeCookieName("uno-remember-me").tokenValiditySeconds(1296000)
.tokenRepository(remmeberMeTokenRepository).and().sessionManagement()
.sessionAuthenticationStrategy(concurrentSessionControlAuthenticationStrategy).maximumSessions(-1);
}
#Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
#Bean
public ConcurrentSessionFilter concurrentSessionFilter(){
return new ConcurrentSessionFilter(sessionRegistry);
}
#Bean
public ConcurrentSessionControlAuthenticationStrategy concurrentSessionControlAuthenticationStrategy(){
return new ConcurrentSessionControlAuthenticationStrategy(sessionRegistry);
}
#Bean
public RegisterSessionAuthenticationStrategy registerSessionAuthenticationStrategy(){
return new RegisterSessionAuthenticationStrategy(sessionRegistry);
}
}
public class SecurityInitializer extends
AbstractSecurityWebApplicationInitializer {
#Override
protected void beforeSpringSecurityFilterChain(ServletContext servletContext) {
insertFilters(servletContext, new MultipartFilter());
}
#Override
protected boolean enableHttpSessionEventPublisher() {
return true;
}
}
public class MvcWebApplicationInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class[] getRootConfigClasses() {
return new Class[] { AppConfig.class };
}
#Override
protected Class[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return new String[] {"/"};
}
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.addListener(new RequestContextListener());
super.onStartup(servletContext);
}
}
public class ConnexionSucessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
#Autowired
UserProfile userProfile;
#Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication auth) throws IOException,
ServletException {
RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
Collection authorities = auth.getAuthorities();
userProfile.loadUser(auth.getName());
for(GrantedAuthority grantedAuthority : authorities){
switch (grantedAuthority.getAuthority()) {
case "ROLE_ADMIN":
redirectStrategy.sendRedirect(request, response, "/admin");
break;
case "ROLE_USER":
redirectStrategy.sendRedirect(request, response, "/user");
break;
}
}
}
}
problem resolved.
I was loading the same configuration twice in both ContextLoaderListener and DispatcherServlet.

Spring MVC 4 java config does not recognize localization change

This is my project structure:
and this is Spring root config:
#EnableWebMvc
#Configuration
#ComponentScan({ "com.rgh.*" })
#EnableTransactionManagement
#Import({ SpringSecurityConfig.class })
public class SpringWebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/assets/**").addResourceLocations("/assets/");
}
// Start localization configs
#Bean
public MessageSource messageSource() {
final ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:messages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
#Bean
public LocaleResolver localeResolver() {
CookieLocaleResolver localeResolver = new CookieLocaleResolver();
localeResolver.setDefaultLocale(new Locale("fa"));
return localeResolver;
}
#Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("lang");
return localeChangeInterceptor;
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
// End localization configs
#Bean
public SessionFactory sessionFactory() {
LocalSessionFactoryBuilder builder = new LocalSessionFactoryBuilder(dataSource());
builder.scanPackages("com.rgh.*.model").addProperties(getHibernateProperties());
return builder.buildSessionFactory();
}
private Properties getHibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.format.sql", "false");
properties.put("hibernate.show.sql", "true");
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
properties.put("hibernate.hbm2ddl.auto", "update");
return properties;
}
#Bean(name = "dataSource")
public BasicDataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/framework");
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}
#Bean
public HibernateTransactionManager txManager() {
return new HibernateTransactionManager(sessionFactory());
}
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/view/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
but when is start the application with localhost:8080, spring does not recognize default locale that set to localeResolver.setDefaultLocale(new Locale("fa")); and load the page with en_US locale and also when i call the page with localhost:8080/?lang=de it load pages with en_US locale again.
Thanks for any idea.
UPDATE
public class SpringWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringWebConfig.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
UPDATE2
These are my new configurations, by default default locale is en_US and messages files does not be loaded, i should open the login page, and enter invalid username and password then press submit, then the messsages_fa.properties will be loaded and locale changed to fa!!!
public class SpringWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { SpringWebConfig.class };
}
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { SpringSecurityConfig.class, SpringPersistanceConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/", "/rest/*" };
}
}
#Configuration
#EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
#Qualifier("userDetailsService")
UserDetailsService userDetailsService;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().frameOptions().sameOrigin();
http.authorizeRequests().antMatchers("/assets/**").permitAll().antMatchers("/admin/**").access("hasRole('ROLE_USER')").and().formLogin().loginPage("/login").failureUrl("/login?error").defaultSuccessUrl("/admin").usernameParameter("username").passwordParameter("password").and().logout().logoutSuccessUrl("/login?logout");
}
}
#Configuration
#EnableTransactionManagement
#ComponentScan(basePackages = { "com.rgh.*" }, excludeFilters = { #Filter(Controller.class) })
public class SpringPersistanceConfig {
#Bean
public SessionFactory sessionFactory() {
LocalSessionFactoryBuilder builder = new LocalSessionFactoryBuilder(dataSource());
builder.scanPackages("com.rgh.*.model").addProperties(getHibernateProperties());
return builder.buildSessionFactory();
}
private Properties getHibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.format.sql", "false");
properties.put("hibernate.show.sql", "true");
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
properties.put("hibernate.hbm2ddl.auto", "update");
return properties;
}
#Bean(name = "dataSource")
public BasicDataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/framework");
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}
#Bean
public HibernateTransactionManager txManager() {
return new HibernateTransactionManager(sessionFactory());
}
}
#Controller
public class BaseController {
#RequestMapping(value = "/admin**", method = RequestMethod.GET)
public ModelAndView adminPage() {
ModelAndView model = new ModelAndView();
model.setViewName("/panel/admin");
return model;
}
#RequestMapping(value = "/login", method = RequestMethod.GET)
public ModelAndView login() {
ModelAndView model = new ModelAndView();
model.setViewName("/panel/login");
return model;
}
}
The problem is that you are loading everything in the root context and some of the beans aren't detected that way. Next to that you should really split your configurations. Create a web, security and persistence configuration and load the security and persistence in the root config and the web in the dispatcher servlet.
#Configuration
#EnableTransactionManagement
#ComponentScan({ "com.rgh"}, excludeFilters = {
#Filter(org.springframework.stereotype.Controller.class)
})
public class PersistenceConfiguration {
// Hibernate, transaction manager, datasource and messageSource go here
}
Then a web configuration
#EnableWebMvc
#Configuration
#ComponentScan({ "com.rgh"}, includeFilters = {
#Filter(org.springframework.stereotype.Controller.class)
}, useDefaultFilters=false )
public class SpringWebConfig extends WebMvcConfigurerAdapter {
/// web related things like view resolvers, controller, interceptors go here
}
Then in your bootstrap class load the correct configuration classes.
public class SpringWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringWebSecurity.class, PersistenceConfiguration.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { SpringWebConfig.class};
}
#Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
Now you have split your configuration and everything is loaded by the correct one. The includeFilter and excludeFilter as well as the useDefaultFilters properties on the component-scan are important here to avoid duplicating beans. If you don't all your beans would be loaded twice once by the root and once by the dispatcherservlet.

Using jdbcAuthentication in Spring Security with Hibernate

I just finished an Spring application which is based on the inMemoryAuthentication(), and now, after verified all are working perfectly, I want use the JDBC Authentication.
I have three kinds of classes to handle the connection to the database:
HibernateConfig, based on the code presented in this blog post.
DAO and Entity class, one for each table from my database (in this current state, I have three: User, Role and User_Role)
And a UserService class, which implement UserDetailsService.
I read some articles on the Internet, and pratically all of them uses the following configuration for the class SecurityConfig:
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private DataSource dataSource;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery(getUserQuery())
.authoritiesByUsernameQuery(getAuthoritiesQuery());
}
What is an issue for me, since I don't have a Datasource class in my project. My current SecurityConfig is this:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.jdbcAuthentication()
.usersByUsernameQuery(getUserQuery())
.authoritiesByUsernameQuery(getAuthoritiesQuery());
}
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.authorizeRequests()
.antMatchers("/css/**", "/fonts/**", "/image/**", "/js/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/spring/index").permitAll()
.loginProcessingUrl("/spring/login").permitAll()
.usernameParameter("login")
.passwordParameter("senha")
.successHandler(new CustomAuthenticationSuccessHandler())
.failureHandler(new CustomAuthenticationFailureHandler())
.and()
.logout()
.logoutUrl("/spring/logout")
.logoutSuccessUrl("/spring/index").permitAll();
}
private String getUserQuery() {
return "SELECT login as username, senha as password "
+ "FROM usuario "
+ "WHERE login = ?";
}
private String getAuthoritiesQuery() {
return "SELECT DISTINCT usuario.login as username, autorizacao.descricao as authority "
+ "FROM usuario, autorizacao_usuario, autorizacao "
+ "WHERE usuario.id = autorizacao_usuario.fk_usuario "
+ "AND autorizacao.id = autorizacao_usuario.fk_autorizacao "
+ "AND usuario.login = ? ";
}
}
As you can see, I already made some adaptations for use JDBC Authentication, but I am still missing the part where I link this class to my Hibernate class.
Someone have any suggestions in how to make this?
my HibernateConfig is this
#Configuration
#EnableTransactionManagement
#PropertySource({ "classpath:persistence.properties" })
#ComponentScan({ "org.webapp.persistence" })
public class HibernateConfig {
#Autowired
private Environment env;
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(restDataSource());
sessionFactory.setPackagesToScan(new String[] { "org.webapp.persistence.model" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public DataSource restDataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassname"));
dataSource.setUrl(env.getProperty("jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.user"));
dataSource.setPassword(env.getProperty("jdbc.pass"));
return dataSource;
}
#Bean
#Autowired
public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory);
return txManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
Properties hibernateProperties() {
return new Properties() {
/**
*
*/
private static final long serialVersionUID = 1L;
{
setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
setProperty("hibernate.globally_quoted_identifiers", "true");
}
};
}
}
Ok, I solved it. All I needed to do was insert the following annotation in my class SecurityConfig:
#ComponentScan(value="org.webapp")
And now I can autowire my DataSource in this class
#Autowired
private DataSource restDataSource;
#Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.jdbcAuthentication()
.dataSource(restDataSource)
.usersByUsernameQuery(getUserQuery())
.authoritiesByUsernameQuery(getAuthoritiesQuery());
}

Resources