Reputation: 193
I've got two issues regarding Spring Security. I did a bunch of research on the web but the answers were either superficial or too complicated for my problem resulting in not much help. I'm trying to use Spring Security in my application applying the Java config strategy (totally xml-less).
First Case I've got a SecurityConfiguration class that extends the WebSecurityConfigurerAdapter. There I've got my autowired loginService (which implements the UserDetailsService) and I've defined the UserDetailsService of AuthenticationManagerBuilder to be my LoginService.
When I try to login using my form the LoginService successfully gets the User (according to the username and password provided), but somehow the authentication fails and I receive a 403 - Access Denied message from Tomcat in the browser.
Second Case As an attempt to fix the previous problem I created a custom AuthenticationProvider and injected it in my SecurityConfiguration . However the method authenticate() did not even work when I tried to login.
Is there anyone who can help me out? Thank you in advance
SecurityConfiguration class
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{
private final String ADMIN_ROLE = "ADMIN";
private final String EMPLOYEE_ROLE = "EMPLOYEE";
@Autowired
private LoginService loginService;
@Autowired
public void configureGlobal ( AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(loginService);
}
@Override
public void configure( WebSecurity web ) throws Exception {
web.ignoring().antMatchers("/resources/**");
}
@Override
public void configure( HttpSecurity http ) throws Exception {
http
.authorizeRequests()
.antMatchers("/login**", "/doLogin**").permitAll()
.antMatchers("/admin", "/admin/**").hasRole(ADMIN_ROLE)
.anyRequest().authenticated()
.and()
.requiresChannel()
.anyRequest().requiresSecure()
.and()
.formLogin()
.loginPage( "/login" )
.loginProcessingUrl( "/doLogin" )
.defaultSuccessUrl( "/admin" )
.failureUrl( "/login?err=1" )
.usernameParameter( "username" )
.passwordParameter( "password" )
.and()
// This is where the logout page and process is configured. The logout-url is the URL to send
// the user to in order to logout, the logout-success-url is where they are taken if the logout
// is successful, and the delete-cookies and invalidate-session make sure that we clean up after logout
.logout()
.logoutRequestMatcher( new AntPathRequestMatcher( "/logout" ) )
.logoutSuccessUrl( "/login?out=1" )
.deleteCookies( "JSESSIONID" )
.invalidateHttpSession( true )
.and()
// The session management is used to ensure the user only has one session. This isn't
// compulsory but can add some extra security to your application.
.sessionManagement()
.invalidSessionUrl( "/login" )
.maximumSessions( 1 );
}
}
LoginService class
@Service("loginService")
public class LoginService implements UserDetailsService{
@Autowired
private HibernateUserDAO hibernateUserDAO;
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
User user = new User();
user.setUsername(username);
List<User> result = hibernateUserDAO.get(user);
user = result.get(0);
return user;
}
}
AuthProvider class
@Component("authProvider")
public class AuthProvider implements AuthenticationProvider {
@Autowired
private LoginService loginService;
@Override
public Authentication authenticate(Authentication auth)
throws AuthenticationException {
String username = auth.getName();
String password = auth.getCredentials().toString();
System.out.println(username + " " + password);
UserDetails user = loginService.loadUserByUsername(username);
System.out.println(user);
if(user != null){
Authentication token = new UsernamePasswordAuthenticationToken(username, password, user.getAuthorities());
return token;
}
return null;
}
@Override
public boolean supports(Class<?> arg0) {
// TODO Auto-generated method stub
return false;
}
}
OBS: the SecurityConfiguration pasted here does not have the AuthProvider injected, but as a matter of information the configureGlobal method should be like this
@Autowired
private AuthProvider authProvider;
@Autowired
public void configureGlobal ( AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authProvider);
}
Upvotes: 4
Views: 3437
Reputation: 193
Problem solved! It seems the hasRole() method of HttpSecurity checks if a role is in the format "ROLE_" (e.g. "ROLE_ADMIN") and my Granted Authorities list was returning only the role name (e.g. "ADMIN"). That's it.
Upvotes: 5