Reputation: 2256
I am running a web application build on spring security version 4.2, spring mvc version 4.2. I want to run customAuthenticationProvider and customAuthenticationSuccessHandler, but customAuthenticationProvider class is not getting called and Request is going to only authentication-failure-url
pom.xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<!-- Spring Security Jars starts-->
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<!-- Spring Security Jars ends-->
application-security.xml
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<http pattern="/resources/css/**" security="none"/>
<http pattern="/resources/img/**" security="none"/>
<http pattern="/resources/js/**" security="none"/>
<http auto-config="false" use-expressions="true">
<!-- <intercept-url pattern="/onemoretime/*" access="hasRole('ROLE_ADMIN')"/>-->
<intercept-url pattern="/admin/*" access="permitAll"/>
<intercept-url pattern="/vendor/*" access="permitAll"/>
<form-login login-page="/login"
username-parameter="username"
password-parameter="password"
authentication-success-handler-ref="customAuthenticationSuccessHandler"
authentication-failure-url="/accessdenied"
/>
<!-- <logout logout-success-url="/login"/> -->
<csrf />
</http>
<authentication-manager alias="authenticationProvider">
<authentication-provider ref="myAuthenticationProvider"/>
</authentication-manager>
<!-- Bean implementing AuthenticationProvider of Spring Security -->
<beans:bean id="myAuthenticationProvider" class="com.opstree.vendorportal.authentication.CustomAuthenticationProvider"/>
<beans:bean id="customAuthenticationSuccessHandler" class="com.opstree.vendorportal.authentication.CustomAuthenticationSuccess"/>
</beans:beans>
web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/service.xml /WEB-INF/application-security.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
loginpage.jsp
<form action="${pageContext.request.contextPath}/login" method="post">
<table>
<tr>
<td>UserName</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>Password</td>
<td><input type="password" name="password"> </td>
</tr>
<tr>
<td align="center" colspan="2">
<div style="color:red" class="servererror">
<c:if test="${not empty userobject}">
<b><c:out value="${userobject.message}"></c:out></b>
</c:if>
</div>
</td>
</tr>
<tr>
<td align="center" colspan="2">
<input type="submit" value="Login">
</td>
</tr>
<tr>
<td align="center" colspan="2">
<b><a href="forgotpassword">ForgotPassword</a></b>
</td>
</tr>
<tr>
<td align="center" colspan="2">
<b>Click here to <a href="registerVendor">Register</a></b>
</td>
</tr>
</table>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
customAuthenticationProvider
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Autowired
private UserDBOperationsImpl userDAO;
private Logger logger = Logger.getLogger(getClass());
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
System.out.println("Spring Security: Entered");
UsernamePasswordAuthenticationToken authenticationToken = (UsernamePasswordAuthenticationToken) authentication;
String username = authenticationToken.getName();
//String password = (String) authenticationToken.getCredentials();
UserBean userBean = null;
try {
userBean = userDAO.getUserDetails(username);
} catch (Exception e) {
logger.error(e.getCause().getMessage());
}
if(userBean == null){
throw new BadCredentialsException("Invalid Credentials");
}
List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
Authentication auth = new UsernamePasswordAuthenticationToken(userBean, userBean.getPassword(), authorities);
System.out.println("Exit");
return auth;
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(getClass());
}
customAuthenticationSuccess
public class CustomAuthenticationSuccess implements AuthenticationSuccessHandler {
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication auth)
throws IOException, ServletException {
System.out.println("Entered Authentication Successful Method");
boolean isUser = false;
Collection<? extends GrantedAuthority> authorities = auth.getAuthorities();
String targetUrl = null;
for(GrantedAuthority currentAuth : authorities){
if(currentAuth.getAuthority().equalsIgnoreCase("ROLE_USER")){
isUser = true;
break;
}
else {
throw new IllegalStateException();
}
}
if(isUser){
targetUrl = "/vendor";
}
System.out.println("Entered Authentication Successful Method");
redirectStrategy.sendRedirect(request, response, targetUrl);
}
}
Upvotes: 0
Views: 3002
Reputation: 6444
I think that what is happening is that the supports(Class<?> authentication)
method in your AuthenticationProvider
is not correctly implemented.
You are checking the Authentication
class received against your CustomAuthenticationProvider
getClass()
method, so as it allways would return false, the AuthenticationManager
will not recognize your provider as a suitable provider for the received UsernamePasswordAuthenticationToken
.
You can check org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider code in github where you could see that a correct implementation for this method in a UsernamePasswordAuthenticationToken
supporting provider should be this way:
public boolean supports(Class<?> authentication) {
return (UsernamePasswordAuthenticationToken.class
.isAssignableFrom(authentication));
}
What I guess is actually happening is that the AuthenticationManager
cannot find a UsernamePasswordAuthenticationToken
supporting provider, so the authentication cannot be performed, and the unauthorized Authentication
is getting to UsernamePasswordAuthenticationFilter
which finally has nothing to do but redirect to the authentication-failure-url
.
Be carefull too with your AuthenticationSuccessHandler
, the way you are checking the GranthedAuthorities
might end with a IllegalStateException
in case the first GranthedAuthority
evaluated is not the ROLE_USER
one:
for(GrantedAuthority currentAuth : authorities){
if(currentAuth.getAuthority().equalsIgnoreCase("ROLE_USER")){
isUser = true;
break;
}
else {
throw new IllegalStateException();
}
}
Upvotes: 1