How to use Custom Captcha and Authentication Manager in Spring Security
28-12-2015Spring Configuration
<http auto-config="false" use-expressions="true" entry-point-ref="loginUrlAuthenticationEntryPoint"> <intercept-url pattern="/index" access="permitAll"/> <intercept-url pattern="/kayit" access="permitAll"/> <intercept-url pattern="/sifre-hatirlatma" access="permitAll"/> <intercept-url pattern="/checkUser" access="permitAll"/> <intercept-url pattern="favicon.ico" access="permitAll"/> <intercept-url pattern="/kullanici/**" access="hasAnyAuthority('ROLE_ADMIN','ROLE_OFFICER','ROLE_CLIENT')"/> <access-denied-handler error-page="/403"/> <custom-filter position="FORM_LOGIN_FILTER" ref="customUsernamePasswordAuthenticationFilter"/> <logout logout-url="/cikis" invalidate-session="true" logout-success-url="/index?logout=true"/> <csrf/> </http> <beans:bean id="loginUrlAuthenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint"> <beans:constructor-arg value="/index"/> </beans:bean> <beans:bean id="customUsernamePasswordAuthenticationFilter" class="com.codesenior.telif.security.CustomUsernamePasswordAuthenticationFilter"> <beans:property name="filterProcessesUrl" value="/login" /> <beans:property name="authenticationFailureHandler" ref="failureHandler"/> <beans:property name="authenticationSuccessHandler" ref="successHandler"/> <beans:property name="authenticationManager" ref="authenticationManager"/> </beans:bean> <beans:bean id="successHandler" class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler"> <beans:property name="defaultTargetUrl" value="/kullanici/index"/> </beans:bean> <beans:bean id="failureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"> <beans:property name="defaultFailureUrl" value="/index?error=true"/> </beans:bean> <!-- Select users and user_roles from database --> <authentication-manager id="authenticationManager"> <authentication-provider user-service-ref="customUserDetailsService"> <password-encoder hash="plaintext"> </password-encoder> </authentication-provider> </authentication-manager>
Login Page
<form method="post" action="<c:url value="/login"/>"> <header class="in_head_1"> <h2 id="pageTitle">ADMIN LOGIN</h2> </header> <article class="art_loop"> <label>Username:</label> <div class="pure-control-group"> <input name="username" type="text" placeholder="Username" maxlength="12" required="true"/> </div> <label>Password:</label> <div class="pure-control-group"> <input name="password" type="password" placeholder="Password" maxlength="20" required="true"/> </div> <c:set var="rand1"><%= java.lang.Math.round(java.lang.Math.random() * 10) %> </c:set> <c:set var="rand2"><%= java.lang.Math.round(java.lang.Math.random() * 10) %> </c:set> <c:set var="rand1" value="${rand1}" scope="session"/> <c:set var="rand2" value="${rand2}" scope="session"/> <label>What is ${rand1}+${rand2} ?</label> <div class="pure-control-group"> <input name="captcha" type="text" placeholder="What is ${rand1}+${rand2} ?" required="true"/> </div> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> <div class="pure-controls"> <button type="submit" class="buttonSubmit">Login</button> </div> </article> </form>
CustomUsernamePasswordAuthenticationFilter
import org.springframework.security.authentication.AuthenticationServiceException; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; public class CustomUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter { @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { super.successfulAuthentication(request, response, chain, authResult); } @Override protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException { super.unsuccessfulAuthentication(request, response, failed); } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { String id = request.getParameter("captcha"); HttpSession session = request.getSession(); int rand1 = Integer.parseInt((String) session.getAttribute("rand1")); int rand2 = Integer.parseInt((String) session.getAttribute("rand2")); if (Integer.valueOf(id) != rand1 + rand2) { throw new AuthenticationServiceException("Please correctly answer: "+rand1+ "+"+rand2); } return super.attemptAuthentication(request, response); } }
CustomUserDetailsService
@Service public class CustomUserDetailsService implements UserDetailsService { @Autowired private UserService userService; 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 UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException { User domainUser = userService.getUser(userName); boolean enabled = true; boolean accountNonExpired = true; boolean credentialsNonExpired = true; boolean accountNonLocked = true; return new org.springframework.security.core.userdetails.User( domainUser.getUsername(), domainUser.getPassword(), enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, getAuthorities(domainUser.getUserRoleList()) ); } public Collection<? extends GrantedAuthority> getAuthorities(List<UserRole> userRoleList) { return getGrantedAuthorities(getRoles(userRoleList)); } public List<String> getRoles(List<UserRole> userRoleList) { List<String> roles = new ArrayList<String>(); for (UserRole userRole : userRoleList) { roles.add(userRole.getRole()); } return roles; } }