Reputation: 1017
Trying to learn spring security using a custom userDetailsService and facing the below issue
When a restricted page ( /admin or /user) is accessed, spring security kicks in and displays the login page.
But after submitting the login page with correct username and password, the access denied page is directly shown before the loadUserByUsername method in my custom userDetailsService implementation is called.
In the logs, there is just the org.springframework.security.access.AccessDeniedException
exception - on accessing the restricted page , no other exceptions.
Code
@Controller
public class TestController {
@RequestMapping("/home")
public String getHomePage() {
return "home";
}
@RequestMapping(value="/user")
public String getUserPage() {
return "user";
}
@RequestMapping(value="/admin")
public String getAdminPage() {
return "admin";
}
}
security config:
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/" access="permitAll"/>
<intercept-url pattern="/login" access="permitAll"/>
<intercept-url pattern="/logout" access="permitAll"/>
<intercept-url pattern="/denied" access="hasRole('ROLE_USER')"/>
<intercept-url pattern="/user" access="hasRole('ROLE_USER')"/>
<intercept-url pattern="/admin" access="hasRole('ROLE_ADMIN')"/>
<form-login login-page="/login"
username-parameter="tmp_usrnm"
password-parameter="tmp_pwd"
authentication-failure-url="/login/failure"
default-target-url="/abcd"/>
<access-denied-handler error-page="/denied"/>
<logout invalidate-session="true"
logout-success-url="/logout/success"
logout-url="/logout"/>
</http>
<authentication-manager>
<authentication-provider user-service-ref="customUserDetailsService">
<password-encoder hash="md5"/>
</authentication-provider>
</authentication-manager>
<beans:bean id="customUserDetailsService" class="com.krishnan.balaji.mc.service.CustomUserDetailsService">
<beans:property name="userRepository">
<beans:bean class="com.krishnan.balaji.mc.repos.UserRepositoryImpl"></beans:bean>
</beans:property>
</beans:bean>
login form:
<!--<form class="login-form" action=<c:url value="j_spring_security_check"/> method="post" >-->
<form action=<c:url value="/login"/> method="post" >
<input id="j_username" name="tmp_usrnm" size="20" maxlength="50" type="text"/>
<input id="j_password" name="tmp_pwd" size="20" maxlength="50" type="password"/>
<p><input type="submit" value="Login"/></p>
</form>
Controller to serve the login/logout/access denied pages
@Controller
public class UserAccessController {
@RequestMapping("/login")
public String login(Model model, @RequestParam(required=false) String message) {
model.addAttribute("message", message);
System.out.println("serving login page");
return "access/login";
}
@RequestMapping(value = "/denied")
public String denied() {
System.out.println("serving access denied page");
return "access/denied";
}
@RequestMapping(value = "/login/failure")
public String loginFailure() {
System.out.println("serving failed login page");
String message = "Login Failure!";
return "redirect:/login?message="+message;
}
@RequestMapping(value = "/logout/success")
public String logoutSuccess() {
System.out.println("serving logout page");
String message = "Logout Success!";
return "redirect:/login?message="+message;
}
}
CustomUserDetailsService
@Service
public class CustomUserDetailsService implements UserDetailsService {
private UserRepository userRepository;;
@Transactional(readOnly = true)
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
System.out.println("loadUserByUsername called");
try {
com.krishnan.balaji.mc.model.User domainUser = userRepository
.getUserByUserName(username);
boolean enabled = true;
boolean accountNonExpired = true;
boolean credentialsNonExpired = true;
boolean accountNonLocked = true;
return new User(domainUser.getUsername(), domainUser.getPassword()
.toLowerCase(), enabled, accountNonExpired,
credentialsNonExpired, accountNonLocked,
getAuthorities(domainUser.getRole().getRole()));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public Collection<? extends GrantedAuthority> getAuthorities(Integer role) {
List<GrantedAuthority> authList = getGrantedAuthorities(getRoles(role));
return authList;
}
public List<String> getRoles(Integer role) {
List<String> roles = new ArrayList<String>();
if (role.intValue() == 1) {
roles.add("ROLE_USER");
roles.add("ROLE_ADMIN");
} else if (role.intValue() == 2) {
roles.add("ROLE_USER");
}
return roles;
}
public static List<GrantedAuthority> getGrantedAuthorities(
List<String> roles) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for (String role : roles) {
authorities.add(new SimpleGrantedAuthority(role));
}
return authorities;
}
public UserRepository getUserRepository() {
return userRepository;
}
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
Upvotes: 0
Views: 1186
Reputation: 10049
In your Spring Security configuration for http
, you should change the following:
default-target-url="/abcd"
to something like
default-target-url="/"
or anything else that you defined.
default-target-url
defines where to go by default when the login process succeeds.intercept-url
from most specific to most genericUpvotes: 0