/j_spring_security_check HTTP error 404 - java

It looks like some filter not added.
I use Spring security 3.2.0.RELEASE with java-config.
Full project posted on GitHub
SecurityConfig.java is here: SecurityConfig.java
I try to set up filter in:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/app/**").hasRole("ADMIN")
.and()
.formLogin()
.loginPage("/")
.defaultSuccessUrl("/app/")
.failureUrl("/?error=1")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/?logout");
}
After csrf().disable() - But problem not solved...
Help me please to solve this problem for I can use /j_spring_security_check with my own CustomUserDetailsService!

I have no experience with Spring Security Java Config, but I checked your code and the API and it seems that setting login processing URL will let you login:
AbstractAuthenticationFilterConfigurer.loginProcessingUrl("/j_spring_security_check")
So your code should be:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/app/**").hasRole("ADMIN")
.and()
.formLogin()
.loginProcessingUrl("/j_spring_security_check")
.loginPage("/")
.defaultSuccessUrl("/app/")
.failureUrl("/?error=1")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/?logout");
}
I would expect this is set by default.
In addition, to make use of MyCustomUserDetailsService, instead of autowiring it as it is now (Proxy created by Spring), I would configure it manually:
public class MyCustomUserDetailsService implements UserDetailsService {
private UserDAO userDAO;
public MyCustomUserDetailsService(UserDAO userDAO) {
this.userDAO = userDAO;
}
// ...
}
Notice, no #Service/#Component annotations and DAO injected via Ctor. In security config:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private DataSource dataSource;
#Autowired
private UserDAO userDAO;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication()
.dataSource(dataSource)
.and()
.userDetailsService(new MyCustomUserDetailsService(userDAO));
}
// ...
}
Now I am sure, the UserDetailService is properly configured. And for sure it will be used while logging in in the application.
I also noticed that the username and password is not used. This is because in login.jsp you use j_username and j_password whereas username parameter should be username and password parameter should be password.
<input type="text" id="username" class="span4" name="username" placeholder="Username" />
<input type="password" id="password" class="span4" name="password" placeholder="Password" />
Look at the FormLoginConfigurer class.

Related

Spring security loginProcessingUrl only works on localhost

I have built an application by using Spring Boot and Thymeleaf. My application works as supposed in my localhost, but when I package it as a .war and deploy it in a test tomcat server, it prompts the login page and then either redirects me to the error page or brings me back to the login page.
I have tried multiple things, and I think that there is an issue with the way I am handling the formLogin() inside my SecurityConfig.java class. More specifically, since Tomcat adds the base-url (e.g. from localhost:8080 to serverUrl:8080/reservation) when uploading my app, the loginProcessingUrl class probably fails to identify the "/process-login" class located on the login.html page.
Please find below my SecurityConfig.java class
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private UserService userService;
private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;
private AccessDeniedHandler accessDeniedHandler;
#Autowired
public SecurityConfig(UserService userService, CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler, AccessDeniedHandler accessDeniedHandler) {
this.userService = userService;
this.customAuthenticationSuccessHandler = customAuthenticationSuccessHandler;
this.accessDeniedHandler = accessDeniedHandler;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login-form-page","/resources/**").permitAll()
.antMatchers("/", "/new-reservation", "/your-reservations","/all-reservations",
"/change-password").hasAnyRole("ADMIN","EMPLOYEE","MANAGER")
.antMatchers("/users","/user-reservations","/arrival-date","/duplicate-reservations","/all-reservations","/registration**")
.hasAnyRole("ADMIN").and()
.formLogin()
.loginPage("/login-form-page")
.loginProcessingUrl("/process-login")
.successHandler(customAuthenticationSuccessHandler)
.permitAll()
.and()
.logout()
.logoutUrl("/login-form-page")
.permitAll()
.and()
.exceptionHandling().accessDeniedHandler(accessDeniedHandler);
}
#Override
public void configure(WebSecurity web) {
web.ignoring()
.antMatchers("/resources/**", "/static/**");
}
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
auth.setUserDetailsService(userService);
auth.setPasswordEncoder(passwordEncoder());
return auth;
}
And here is a small sample of the login.html page.
<div class="form-container sign-in-container">
<form id="loginForm" name="regForm" th:action="#{/process-login}"
method="POST">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
<h1>Sign In</h1>
<!-- Login Error -->
<div th:if="${param.error}"
class="alert alert-danger col-xs-10">Wrong email and/or password</div>
<!-- Logout notify -->
<div th:if="${param.logout}"
class="alert alert-success 1 col-xs-10">You
have been logged out.</div>
All the .html pages are located in
-resources
-templates
Lastly, the only error I see in the logs is the following
DEBUG o.s.w.s.r.ResourceHttpRequestHandler - Resource not found
For anyone interested, I managed to solve the above issue. It seems like it was not a misconfiguration in the loginProcessingUrl() class. Instead, the issue was the way a remote server handles the JSESSIONID and csrf.
More specifically, what I had to do is
Added the following block of code in my SecurityConfig.java
cookieServerCsrfTokenRepository.setCookieHttpOnly(false);
http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
Next, added the block of code below
#Bean
public ServletContextInitializer servletContextInitializer(#Value("${secure.cookie}") boolean secure) {
return new ServletContextInitializer() {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.getSessionCookieConfig().setSecure(secure);
}
};
}
The secure.cookie value needs to be set (in the application.properties to true if you intend to utilise the HTTPs protocol.

Spring Security: How to allow access to only login page using OAuth 2.0?

I have a Spring Boot project using Spring Security and OAuth2.0 libraries.
I confirmed when I accessed http://localhost:8080/login, the default login view is displayed and I could log in.
But if I implement Config class shown below:
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers( "/login**" ).permitAll()
.anyRequest()
.authenticated();
}
}
The browser returns "404 not found error".
I thought I could be authenticated directly accessing to a Github's API, so implemented this, but it Wouldn't work:
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String login(){
return "redirect:/oauth2/authorization/github";
}
How should I cope with that? I know I probably have some misunderstandings because of a lack of my knowledge,
but I only want to know how to allow access to only a login page when a user is not authenticated.
Thanks.
finally solved!
I need to append following parts to the end of the methods flow.
.and()
.oauth2Login()
.loginPage("/login");
so the final code is:
SecurityConfig.java
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login**")
.permitAll()
.anyRequest()
.authenticated()
//appended
.and()
.oauth2Login()
.loginPage("/login");
}
}
Controller.java
#GetMapping(value = "/login")
public String getit(Model model){
return "login";
}
login.html
<body>
<a th:href="#{/oauth2/authorization/github}">Login</a>
</body>
It worked!
Referenced URL:https://www.codeflow.site/ja/article/spring-security-5-oauth2-login

Spring Security not serving static content

I'm trying to get spring security to allow the serving of static files like .css .js etc. without need to login first.
I've tried creating MVC config with resource handler and changing rules in spring security config, but nothing seems to be working.
MvcConfig.java:
#Configuration
#EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/assets/**")
.addResourceLocations("/assets/");
}
}
SecurityConfig.java:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/", "/assets/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
#Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers("/assets/**");
}
}
When I go to http://localhost:8080/assets/js/particles.min.js I'm expecting it to return the file contents but every time I try links like localhost:8080/assets/* it returns the content of login.html
My assets files
My project files
Supposing that your static files are under src/main/resources:
There are two main pieces to configure:
Implement the WebMvcConfigurer interface to discover your static resources:
#Configuration
public class MvcConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!registry.hasMappingForPattern("/assets/**")) {
registry.addResourceHandler("/assets/**")
.addResourceLocations("/assets/");
}
}
}
Setup your security configuration to allow static resources (such as CSS, JavaScripts and images) to be publicly accessible:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
// Your settings
#Override
protected void configure(HttpSecurity http) throws Exception {
// Your AuthN handlers and filter chain...
http
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/css/**").permitAll()
.antMatchers("/img/**").permitAll()
.antMatchers("/js/**").permitAll()
.anyRequest().authenticated();
// Logout handler...
}
}
Supposing that you have a CSS file as follows:
src/main/resources/assets/css/layout.css
The web server will make it accessible at:
http://<root_url>:<port>/css/layout.css
Try to change to:
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/assets/").permitAll()
.and()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
web.ignoring().antMatchers("/assets/**");
The statement above will tell spring security to Ignore any request that starts with “/assets/”. So if i were you, i will remove all the following configuration:
.antMatchers("/", "/assets/**")
.permitAll()
fom the configure(HttpSecurity http) method.

How to route a landing page to a Spring Boot Application?

I'm trying to add a landing page to a Spring Application that I created so that when the application initially loads the landing page is the first page that is seen. The issue is, I created the landing page after I created the application and so the application loads a login/register page first and I cannot route the landing page to open first. I'm trying to research online where I could possibly complete this task yet I'm lost and would really appreciate some help.
I've included the WebSecurityConfig file below.
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/resources/**", "/registration").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
//Disable csrf token as it is not needed for now and is preventing the applciation from running properly
http.csrf().disable();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
}

Moving Spring Security To Java Config, where does authentication-success-handler-ref go?

Our app has a custom success handler for successful logins. It basically redirects them to the page they were on when their session expired.
We're moving to a Java config rather than a spring xml config. The rest of the config went very smoothly, but we can't find where to put the authentication-success-handler-ref attribute of the security:form-login tag.
<security:http auto-config='true'>
...
<security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY"/>
<security:form-login login-page="/login" default-target-url="/sites"
authentication-failure-url="/login"
authentication-success-handler-ref="authenticationSuccessHandler"/>
...
Here's our config, so far.
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.failureUrl("/login")
.and()
.logout()
.permitAll()
.and()
}
Also, we can't find where to put default-target-url, but that is definitely less important.
Caveat, we're actually using Groovy, but the code is basically the same as a Java config.
All settings can be done inside the global configure method. Add the following:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/sites")
.failureUrl("/login")
.successHandler(yourSuccessHandlerBean) // autowired or defined below
.and()
.logout()
.permitAll()
.and()
}
You have to create bean extending SimpleUrlAuthenticationSuccessHandler or SavedRequestAwareAuthenticationSuccessHandler. For example:
#Bean
public SavedRequestAwareAuthenticationSuccessHandler successHandler() {
SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
successHandler.setTargetUrlParameter("/secure/");
return successHandler;
}
Then you have to setup it on bean extending AbstractAuthenticationProcessingFilter:
UsernamePasswordAuthenticationFilter authenticationFilter = new UsernamePasswordAuthenticationFilter();
authenticationFilter.setAuthenticationSuccessHandler(successHandler());

Categories