Spring Security for Hawt.io - java

I would like to configure Spring Security for Hawt.io with embedded tomcat. After custom login with (user and password) Hawt.io login is asking to authenticate.But Hawt.io authentication is disabled in code and in config. If I remove MvcConfig and WebSecurityConfig with security.basic.enable= false then without any authentication which works.But
I want to authenticate with custom username and password which is
working after that Hawt.io is also asking the credentials though that
part is disabled.
Please help me to resolve this.
application.properties
hawtio.authenticationEnabled = false
management.security.enabled=false
security.basic.enable= true
security.ignored= /**
login.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Spring Security Example </title>
</head>
<body>
<div th:if="${param.error}">
Invalid username and password.
</div>
<div th:if="${param.logout}">
You have been logged out.
</div>
<form th:action="#{/login}" method="post">
<div><label> User Name : <input type="text" name="username"/> </label></div>
<div><label> Password: <input type="password" name="password"/> </label></div>
<div><input type="submit" value="Sign In"/></div>
</form>
</body>
</html>
MvcConfig.java
#Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
}
}
WebSecurityConfig.java
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/","/hawtio").permitAll().anyRequest().authenticated().and()
.formLogin().loginPage("/login")
.permitAll().and().logout().permitAll();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
}
}
Application.java
#SpringBootApplication
#EnableHawtio
public class Application {
public static void main(String[] args) {
System.setProperty(AuthenticationFilter.HAWTIO_AUTHENTICATION_ENABLED, "false");
SpringApplication.run(Application.class, args);
}
}
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.8.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>io.hawt</groupId>
<artifactId>hawtio-springboot</artifactId>
<version>1.5.6</version>
</dependency>
<dependency>
<groupId>io.hawt</groupId>
<artifactId>hawtio-core</artifactId>
<version>1.5.6</version>
</dependency>
</dependencies>
Update:
Connect to dummy camel app like below login for again comes on giving credentials going to 404 error page.

The following changes are required to make hawtio work with Spring Security and Spring Boot. You can find a working example here. However, I wasn't able to update the username in hawtio menubar.
Configure Spring Security
Configure Spring security for application in a standard way except for
a few changes specfic to hawtio:
Disable hawtio authentication,
#SpringBootApplication
#EnableHawtio
#ComponentScan(basePackages = {"com.basaki"})
public class Application {
public static void main(String[] args) {
System.setProperty(AuthenticationFilter.
HAWTIO_AUTHENTICATION_ENABLED,"false");
SpringApplication.run(Application.class, args);
}
}
Disable Cross-Site Request Forgery (CSRF) in your application.
Make sure the logout request URL matches the /hawtio/auth/logout/*.
This is the URL used by hawtio to invalidate a session.
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
...
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/").permitAll()
.anyRequest().authenticated()
.and().formLogin().loginPage("/login")
.failureUrl("/login?error")
.permitAll()
.and().logout().logoutRequestMatcher(
new AntPathRequestMatcher(
"/hawtio/auth/logout/*"))
.logoutSuccessUrl("/login?logout")
.and().csrf().disable();
}
...
}
Login Page
Since you are using a form login, you will be needing a custom login page. In this example, a login.html is used.
Configure the /login request to match view login.html
#Configuration
public class SpringMvcConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
}
...
}
Updating hawtio's login.html
Once you log out from the hawtio page, it takes you to its own login page. Since it's a single page application with AngularJS, you need to replace this partial page with your own custom AngularJS based login page.
In this example, a login-hawtio.html page is used.
<div ng-controller="LoginPlugin.LoginController">
<h1 style="color: #78ab46;">Sign in</h1>
<form action="/login" method="post">
<div>
<label style="font-weight: 700; padding-right: 15px;
padding-left: 15px;">Username:
<input id="username" type="text" name="username"
placeholder="Username"/>
</label>
</div>
<div>
<label style="font-weight: 700; padding-right: 15px;
padding-left: 15px;">Password:
<input id="password" type="password"
name="password" required
placeholder="Password"/>
</label>
</div>
<div>
<button type="submit" class="btn btn-default">Sign In</button>
</div>
</form>
</div>
A controller to replace the existing hawtio login page.
#Controller
public class HawtioController {
private ResourceLoader loader;
#Autowired
public HawtioController(ResourceLoader loader) {
this.loader = loader;
}
#RequestMapping(value = "/hawtio/app/core/html/login.html", method = RequestMethod.GET,
produces = "text/html;charset=UTF-8")
public void getHawtioLoginHtml(HttpServletResponse response) {
String location = "classpath:/templates/login-hawtio.html";
try {
String body = getResource(location);
response.setStatus(HttpStatus.OK.value());
response.getWriter().write(body);
response.getWriter().flush();
response.getWriter().close();
} catch (IOException e) {
response.setStatus(HttpStatus.NOT_FOUND.value());
}
}
...
}
hawtio Login Plugin
A custom hawtio plugin is needed to have your own AngularJS login controller, LoginPlugin.LoginController. It's used for redirecting to hawtio's home page after you are logged in from hawto's login page.
#Configuration
public class HawtioConfiguration {
#Bean
public HawtPlugin samplePlugin() {
return new HawtPlugin("login-plugin",
"/hawtio/plugins",
"",
new String[]{"plugin/js/login-plugin.js"});
}
}
The login-plugin.js is located under resources/app/webapp/plugin/js folder.
var LoginPlugin = (function(LoginPlugin) {
LoginPlugin.pluginName = 'login-plugin';
LoginPlugin.log = Logger.get('LoginPlugin');
LoginPlugin.module = angular.module('login-plugin', ['hawtioCore'])
.config(function($routeProvider) {
$routeProvider.
when('/home', {
templateUrl: '/hawtio/index.html'
});
});
LoginPlugin.module.run(function(workspace, viewRegistry, layoutFull) {
LoginPlugin.log.info(LoginPlugin.pluginName, " loaded");
viewRegistry["login-plugin"] = layoutFull;
workspace.topLevelTabs.push({
id: "LoginPlugin",
content: "Login Plugin",
title: "Login plugin loaded dynamically",
isValid: function(workspace) { return true; },
href: function() { return "#/login-plugin"; },
isActive: function(workspace) {
return workspace.isLinkActive("login-plugin"); }
});
});
LoginPlugin.LoginController = function($scope, $rootScope, $http) {
var fullUrl = "/hawtio/index.html";
$http({method: 'GET', url: fullUrl});
};
return LoginPlugin;
})(LoginPlugin || {});
hawtioPluginLoader.addModule(LoginPlugin.pluginName);

Related

Spring Security simple login page cant login

So I am trying to creating simple Login Page with help of the Spring Boot and Security. So what I currently have is custom login page and in memory authentication with one user and role.
The problem is that when I am entering proper user/password spirng is not authenticating it as valid data, and redirecting me again to login page, but this time with: /login#error
On client side I am using thymeleaf.
form snippet:
<form th:action="#{/perform_login}" method="post">
<input name="user" placeholder="Username" /> <br />
<input name="pass" placeholder="Password" /> <br />
<input type="submit" value="Login" />
</form>
Configuration class:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()//
.withUser("root").password("root").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests() //
.antMatchers("/").hasRole("USER") //
.antMatchers("/login*").permitAll().and() //
.formLogin() //
.loginPage("/login")//
.loginProcessingUrl("/perform_login")//
.and()//
.logout()//
.permitAll();
}
}
And controller is simple
#Controller
#RequestMapping("/login")
public class LoginController {
#GetMapping
public String getLoginPage() {
return "login";
}
}
Any idea what I am doing wrong?
The easiest way (for me) is to make a #Bean and use WebSecurityConfigurerAdapter and implement WebMvcConfigurer to configure everything with few steps. This is the smallest example ever made:
#Configuration
#SpringBootApplication
public class DemoApplication implements WebMvcConfigurer {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Controller
public class HomeController {
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Model model, Authentication authentication, Principal principal) {
if (authentication == null) {
return "forward:/login";
} else {
model.addAttribute("user", principal.getName());
return "home";
}
}
}
#Bean
public WebSecurityConfigurerAdapter webSecurityConfig() {
return new WebSecurityConfigurerAdapter() {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.anyRequest().authenticated()
.and().formLogin().loginPage("/login")
.defaultSuccessUrl("/")
.permitAll()
.and().logout().permitAll();
http.headers().frameOptions().disable();
}
#Override
protected void configure(AuthenticationManagerBuilder builder) throws Exception {
builder.authenticationProvider(new AuthenticationProvider() {
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = authentication.getCredentials().toString();
if (username.equals("username") && password.equals("password")) {
List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_USER"));
return new UsernamePasswordAuthenticationToken(username, password, grantedAuthorities);
}
throw new AuthenticationServiceException("Invalid credentials.");
}
#Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
});
}
};
}
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/home").setViewName("home");
registry.addViewController("/login").setViewName("login");
}
}
You said that you are using thymeleaf so lets say your login.html form will be something like this:
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>login example</title>
</head>
<body>
<form th:action="#{/login}" method="post">
<input name="username" placeholder="Username"/> <br/>
<input name="password" placeholder="Password"/> <br/>
<input type="submit" value="Login"/>
</form>
</body>
</html>
And the home.html page when you are logged in:
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>home page</title>
</head>
<body>
Hello, <span th:text="${user}"></span><br>
sign out
</body>
</html>

Spring Security LDAP Authentication with custom login

I don't know how to do some stuff with spring security and I hope you guys can you help me.
I have two controllers: one for login page and one for home page
#RestController
#RequestMapping("/rest/hello")
public class LoginController {
#GetMapping(value="/login")
public String getLoginPage(Model model){
return "login";
}
}
and
#RestController
#RequestMapping("/rest/hello")
public class HomeController {
#GetMapping("/home")
public String getHomePage() {
return "homePage";
}
}
For this controllers I have html pages,
login.html
<body>
<div class="limiter">
<div class="container-login100">
<div class="wrap-login100">
<div class="login100-form-title" style="background-image: url(images/bg-01.png);">
</div>
<form class="login100-form validate-form">
<div class="wrap-input100 validate-input m-b-26" data-validate="Username is required">
<span class="label-input100">Username</span>
<input class="input100" type="text" name="username" placeholder="Enter username">
<span class="focus-input100"></span>
</div>
<div class="wrap-input100 validate-input m-b-18" data-validate = "Password is required">
<span class="label-input100">Password</span>
<input class="input100" type="password" name="pass" placeholder="Enter password">
<span class="focus-input100"></span>
</div>
<div class="flex-sb-m w-full p-b-30">
<div class="contact100-form-checkbox">
<input class="input-checkbox100" id="ckb1" type="checkbox" name="remember-me">
<label class="label-checkbox100" for="ckb1">
Remember me
</label>
</div>
<div>
</div>
</div>
<div class="container-login100-form-btn">
<button class="login100-form-btn">
Login
</button>
</div>
</form>
</div>
</div>
</div>
ldif file and a configuration that looks like that:
#EnableGlobalMethodSecurity
#Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().fullyAuthenticated()
.and()
.formLogin();
}
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.ldapAuthentication()
.userDnPatterns("uid={0},ou=people")
.groupSearchBase("ou=groups")
.contextSource(contextSource())
.passwordCompare()
.passwordEncoder(new LdapShaPasswordEncoder())
.passwordAttribute("userPassword");
}
#Bean
public DefaultSpringSecurityContextSource contextSource() {
return new DefaultSpringSecurityContextSource(Arrays.asList("ldap://localhost:8389/"),
"dc=springframework,dc=org");
}
}
First of all, I want to use my login form not the default form. If I try to do this in my configuration
.formLogin().loginPage("/login");
I receive this error: This page isn’t working
localhost redirected you too many times.
Try clearing your cookies
And my second problem is that after authentication I want to redirect me to the home page but instead I receive the a message with the name of the html file: "homePage"
You might try the following.
Change the login REST controller #Get Mapping .
#RestController
#RequestMapping("/rest/hello")
public class LoginController {
#GetMapping(value="/dologin") // <---- new
public String getLoginPage(Model model){
return "login";
}
}
Match the above "/dologin" to the change in the Http configure method.
.formLogin().loginPage("/dologin");

Spring Boot custom login page displays 404

Hi I'm currently trying to set up a simple login page using Spring Boot Security but whenever I try to access the login view I get a 404 "page not found" error.
Security Config:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN");
}
}
Login view, using freemarker (located at main/resources/templates/login.ftl):
<body class="login">
<div>
<div class="login_wrapper">
<div class="animate form login_form">
<section class="login_content">
<form>
<h1>Login Form</h1>
<div>
<input type="text" class="form-control" placeholder="Username" required="" />
</div>
<div>
<input type="password" class="form-control" placeholder="Password" required="" />
</div>
<div>
<a class="btn btn-default submit" href="/units">Log in</a>
</div>
<div class="clearfix"></div>
</form>
</section>
</div>
</div>
</div>
</body>
Anyone know what I'm doing wrong? Thanks for the help!
You need to have a view controller for /login. either write a controller for that or following will do.
#EnableWebMvc
#ComponentScan("package_name")
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
// ...
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
}
To setup view rosolver:
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/pages/");
resolver.setSuffix(".ftl");
return resolver;
}
Now put your ftl files inside webapp/WEB-INF/pages directory. You're all set.

Including css and javascript files in spring 4 project

I'm making a web app using Spring 4, the Spring security module and tomcat 8. I'm trying to include some css files and js files in a .jsp file, but it's not working. When I check in the sources tag in Chrome the content of the css seems to be a log in form. I suspect that it may have something to do with spring security.
My css file is included like this in the .jsp
<link href="<c:url value='resources/css/materialize.min.css' />" rel="stylesheet"
type="text/css"></link>
This is the WebConfig file
#Configuration
#ComponentScan(basePackages = "mypackage")
#EnableWebMvc
#EnableTransactionManagement
public class WebAppConfig extends WebMvcConfigurerAdapter {
#Bean
public InternalResourceViewResolver viewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
}
#Autowired
#Bean
public HibernateTransactionManager transactionManager(SessionFactory sessionFactory){
HibernateTransactionManager transactionManager = new HibernateTransactionManager(sessionFactory);
return transactionManager;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
This is the SecurityConfig file
public class SecurityConfig extends WebSecurityConfigurerAdapter {
...
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/js/**", "/resources/css/**", "/resources/img/**", "/resources/font/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().loginPage("/signin")
.failureUrl("/signin?param.error=bad_credentials")
.and().logout().logoutUrl("/signout")
.and().authorizeRequests()
.antMatchers("/favicon.ico", "/resources/css/**", "/resources/font/**",
"/resources/js/**", "/auth/**", "/signin/**", "/signup/**", "/disconnect/facebook").permitAll()
.antMatchers("/**").authenticated()
.and()
.rememberMe().
and().csrf();
}
}
According to other answers here in stackoverflow it should work with the code that I have but the css only returns this:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:social="http://spring.io/springsocial"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorator="layout">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<div id="content" >
<form id="signin" action="signup" method="post">
<input type="hidden" name="" value=""/>
<div class="formInfo">
</div>
<fieldset>
<label for="login">Email</label>
<input id="login" name="email" type="text" size="25"></input>
<label for="Nombre">Email</label>
<input id="nombre" name="nombre" type="text" size="25"></input>
<label for="password">Password</label>
<input id="password" name="contrasena" type="password" size="25"></input>
</fieldset>
<button type="submit">Sign In</button>
<p>Or you can signin with a new account.</p>
</form>
</div>
All my css and js files are inside WebContent/resources
I solved the problem, apparently there was an ambiguous routing in one of my controllers, so when I tried to access a url that started with "/resources" it routed it to the controller, and thus returned a .jsp instead of the css/js/image. My original controller binded the url in the #Controller, and left the #RequestMapping without indicating the route.
#Controller("/signup")
public class SignUpController {
#RequestMapping(method=RequestMethod.GET)
public String signUpForm(){
...
}
#RequestMapping(method=RequestMethod.POST)
public String crearUsuario(HttpServletRequest request){
...
}
So I changed the #Controller annotation, and put the url in each #RequestMapping like this:
#Controller
public class SignUpController {
#RequestMapping(value="/signup", method=RequestMethod.GET)
public String signUpForm(){}
#RequestMapping(value="/signup",method=RequestMethod.POST)
public String crearUsuario(HttpServletRequest request){}
}

Spring Security 3 - always return error 302

I use Spring 4 to create a simple application. Recently, I'm adding Spring Security 3 to the project but always get the Error Code 302 ( so it redirect to home page always ).
Here is my SecurityConfig:
#Configuration
#EnableWebMvcSecurity
#ComponentScan(basePackages = { "com.moon.repository" })
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("hello").password("world").roles("USER");
}
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring().antMatchers("/resources/**", "/views/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/","/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/home")
.loginProcessingUrl("/acct/signin")
.and()
.logout()
.permitAll();
}
}
I have a Controller called AccountController:
#Controller
#RequestMapping(value = "/acct")
public class AccountController {
private final Logger logger = LoggerFactory.getLogger(AccountController.class);
#RequestMapping(value = "/signin", method = RequestMethod.POST)
public String signin(#RequestParam("username") String username,
#RequestParam("password") String password) {
logger.info("======== [username:{0}][password:{1}] ========", username, password);
if ("error#1.1".equalsIgnoreCase(username)) {
return "error";
} else {
return "demo";
}
}
}
My WEB-INF structure:
WEB-INF
----views
--------home.jsp
--------demo.jsp
--------error.jsp
The flow is like:
User access the web site with http://mylocal:8080/moon => it shows home.jsp
User press the button SignIn and it pops a sub-window asked for username and password => still in home.jsp
User press Submit button => I assume it will go /acct/signin and return to /demo, but I see Error 302 in Google Chrome and then it goes to /home again
Any ideas ? I'm stuck in 2 full days and now i'm almost in despair...
thank you very much every one to take a look at my problem
=================================== 1st Update ===================================
Update: The form in home.jsp
<form:form role="form" method="POST" action="acct/signin"
class="form-signin">
<div class="row">
<div class="col-lg-5">
<input name="username" size="20" type="email"
class="form-control" placeholder="Email address" required
autofocus>
<input name="password" type="password"
class="form-control" placeholder="Password" required>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</div>
</div>
</form:form>
=================================== 2nd Update ===================================
I tried to implement UserDetailsService(not to use in-memory auth) but still... the same problem - Error 302
AppUserDetailsServiceImpl.java
#Component
public class AppUserDetailsServiceImpl implements UserDetailsService {
private final Logger logger = LoggerFactory.getLogger(AppUserDetailsServiceImpl.class);
#Override
public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException {
logger.info("loadUserByUsername username=" + username);
logger.info("======== {} ========",SecurityContextHolder.getContext().getAuthentication());
if (!username.equals("hello")) {
throw new UsernameNotFoundException(username + " not found");
}
// creating dummy user details
return new UserDetails() {
private static final long serialVersionUID = 2059202961588104658L;
#Override
public boolean isEnabled() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public String getUsername() {
return username;
}
#Override
public String getPassword() {
return "world";
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<SimpleGrantedAuthority> auths = new java.util.ArrayList<SimpleGrantedAuthority>();
auths.add(new SimpleGrantedAuthority("USER"));
return auths;
}
};
}
The log shows:
[14/08/19 15:16:32:200][INFO ][com.moon.repository.AppUserDetailsServiceImpl][loadUserByUsername](24) loadUserByUsername username=hello
[14/08/19 15:16:32:200][INFO ][com.moon.repository.AppUserDetailsServiceImpl][loadUserByUsername](25) ======== org.springframework.security.authentication.UsernamePasswordAuthenticationToken#f1e4f742: Principal: com.moon.repository.AppUserDetailsServiceImpl$1#e3dc1b1; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#12afc: RemoteIpAddress: 127.0.0.1; SessionId: 023BC9A8B997ECBD826DD7C33AF55FC7; Granted Authorities: USER ========
I believe Spring is redirecting you to /home because you didn't actually authenticated a User through the login process.
You access your web-app through http://mylocal:8080/moon returning the home.jsp view
You click the SignIn button, submitting your login form since no form login is explicitly declared, Spring Security will display the username and password prompt box for the end-user to enter its credentials
These credentials are then POSTed to the login processing URL (/acct/signin) for which you happen to have a mapping with the signin method in the AccountController
Such controller fails to authenticate a User the Spring way, but still redirect the request to /demo by returning a String
The /demo path is protected (.anyRequest().authenticated()) to any unauthenticated user, since the current user is indeed unauthenticated, Spring Security will automatically redirect the request to the login page
You end up on /home (.loginPage("/home"))
Using a InMemoryUserDetailsManagerConfigurer (see inMemoryAuthentication javadoc), you can only successfully login through the configured credentials. If you want a fully-fledged Authentication system, you must provide an UserDetailsService implementation to your Spring Security configuration (through the userDetailsService method).
EDIT : Following the conversation with chialin.lin, it seems the missing configuration was a defaultSuccessfulUrl for Spring Security to know where to redirect the user once authenticated.
To avoid having to create a new trivial SuccessHandler, override the successfulAuthentication method in your filter and just call the chain.doFilter() method after having set the Authentication object in the security context.
For me I came from a little different use-case but 'suddenly' had the same problem before it perfectly worked.
My Setup Spring with a ExtJs frontend where I now build in a rest interface.
It all worked super nice and then suddenly I started having http status 302 responses (WTH?)
Since I implemented by code by following this example: https://octoperf.com/blog/2018/03/08/securing-rest-api-spring-security/
there is a declaration of a SimpleUrlAuthenticationSuccessHandler.
See 4.4 SecurityConfig where the TokenAuthenticationFilter is constructed with a class NoRedirectStrategy; see 4.1 Redirect Strategy
In turn not having this NoRedirectStrategy set up in my extension of the AbstractAuthenticationProcessingFilter it would show me http 302 responses.
I had a problem with the following:
In my html that I set in the login settings
I didn't put /
In the end I was able to
<form class="form-signin" method="post" action="auth/login">
but it should have been
<form class="form-signin" method="post" action="/auth/login">
As a result, i could not login > got a 302 redirect error > and redirected again to a broken login page.
This is what the full working page looks like.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login customer</title>
</head>
<body>
<div class="container">
<form class="form-signin" method="post" action="/auth/login">
<h2 class="form-signin-heading">Login</h2>
<p>
<label for="username">Username</label>
<input type="text" id="username" name="username" class="form-control" placeholder="Username" required>
</p>
<p>
<label for="password">Password</label>
<input type="password" id="password" name="password" class="form-control" placeholder="Password" required>
</p>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>
</div>
</body>
</html>

Categories