//Part of my Controller class
@RequestMapping("/login")
public String login(HttpServletRequest request,HttpServletResponse response) {
request.setAttribute("mode", "MODE_LOGIN");
return "welcomepage";
}
@RequestMapping ("/login-user")
public String loginUser(@ModelAttribute User user, HttpServletRequest request,HttpServletResponse response) {
if((userService.findByUsernameAndPassword(user.getUsername(), user.getPassword())!=null)) {
Cookie loginCookie=new Cookie("mouni","user.getUsername()");
loginCookie.setMaxAge(30*5);
response.addCookie(loginCookie);
return "homepage";
}
else {
request.setAttribute("error", "Invalid Username or Password");
request.setAttribute("mode", "MODE_LOGIN");
return "welcomepage";
}
}
I am doing a library management project on java spring boot. I have one problem, i would like to do authentication using cookies. In brief, Once after user logged in with his credentials, username should be saved as cookie value. Next time when user is going to login, he can just enter username and should be logged in successfully. Could someone please help me out
Since security is a complex matter, I recommend using Spring Security, even though you're tasked to do it without. To illustrate the complexity about security, I can already tell you that your current code has a vulnerability, since you're trusting a plaintext username cookie as your sole authentication. Spring Security on the other hand uses a key to generate a remember me cookie so that it is much more difficult to impersonate someone (unless you know the key).
So, if you would be using Spring Security, the first thing you need to do is to create a UserDetailsService
, which has a method called loadByUsername()
. To implement this, you could use your UserService
and use the User
builder to construct a Spring Security user object:
public class MyUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if ("admin".equalsIgnoreCase(username)) {
return User.builder()
.username(username)
// This should contain the hashed password for the requested user
.password("$2a$10$T5viXrOTIkraRe2mZPyZH.MAqKaR6x38L.rbmRp53yQ8R/cFrJkda")
// If you don't need roles, just provide a default one, eg. "USER"
.roles("USER", "ADMIN")
.build();
} else {
// Throw this exception if the user was not found
throw new UsernameNotFoundException("User not found");
}
}
Be aware, in contrary to your original UserService.findByUsernameAndPassword()
you do not have to check the password by yourself, just retrieve the user object and pass the hashed password.
The next step is to provide a proper PasswordEncoder
bean. In my example I'm using BCrypt with 10 rotations, so I created the following bean:
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(10);
}
@Bean
public UserDetailsService userDetailsService() {
return new MyUserDetailsService();
}
}
The next step is to configure Spring Security. For example:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/**")
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login.html").permitAll()
.loginProcessingUrl("/login-user").permitAll().usernameParameter("username").passwordParameter("password")
.defaultSuccessUrl("/welcome.html")
.and()
.rememberMe()
.alwaysRemember(true)
.tokenValiditySeconds(30*5)
.rememberMeCookieName("mouni")
.key("somesecret")
.and()
.csrf().disable();
}
In this case, all endpoints (/**
) will be secured, you'll have a login form at login.html
containing two form fields (username
and password
). The destination of the form should be /login-user
and when a user is successfully logged in, he will be redirected to /welcome.html
.
Similar to what you wrote in your code, this will generate a cookie called mouni
containing a value (no longer a plain username) and it will be valid for 150 seconds, just like in your example.
I'm disabling CSRF here because I'm using a simple HTML form, and otherwise I would have to add a templating engine to pass the CSRF key. Ideally, you should keep this enabled.
You are using Spring framework which has the capability for the same which you are trying to achieve. so why to do it manually?
Have a look at spring security.
https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With