Spring ZKoss Customized Login, Logout, Authorization and Authentication

Reading Time: 2 minutes

CustomAuthenticationFilter.java

public class CustomAuthenticationFilter extends
		UsernamePasswordAuthenticationFilter {

	@Autowired
	private xxService xService;
	
	static final Logger logger = Logger.getLogger(CustomAuthenticationFilter.class);

	


	@Override
	public Authentication attemptAuthentication(HttpServletRequest request,
			HttpServletResponse response) throws AuthenticationException {

		
		String username = request.getParameter(getUsernameParameter());
		String password = request.getParameter(getPasswordParameter());
		String server = request.getParameter("server");
		
		
		if(username.trim().length() == 0 || password.trim().length() == 0){
			logger.error("Error empty credentials entered " + username + password + server);
			throw new BadCredentialsException("Error empty credentials entered!");
		}
		
		return logonToBO(request, response, username, password, server);
	}
	
	public Authentication logonToBO(HttpServletRequest request, HttpServletResponse response, String username, String password, String server){
		
		List<GrantedAuthority> authorities = collectAuthorities(username, password, server);
		
		UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password, authorities);		
		
		if(xService.checkUserEnterpriseLogOn(username, password,server)){
			logger.debug("Access granted " + username+ password + server + token);
			return token;
		}else{
			throw new BadCredentialsException("Error wrong credentials entered!");
		}
	}
	
	public List<GrantedAuthority> collectAuthorities(String username, String password, String server){
		
		List<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
		
		String userAuth = xService.acquireUserAuthorityGroup(username, password, server);

		if(userAuth.equals("YOUR_CUSTOM_AUTH_VALUE")){
			auths.add(new GrantedAuthorityImpl("ROLE_USER"));
			
		}
		
		if(userAuth.equals("") || userAuth == ""){
			logger.error("Unauthorized login " + username);
			throw new BadCredentialsException("You aren't authorized beyond this point!");
		}		
		return auths;
	}
}

CustomAuthenticationProvider.java

public class CustomAuthenticationProvider implements AuthenticationProvider{

	public Authentication authenticate(Authentication authentication)
			throws AuthenticationException {

		return authentication;
	}	


	public boolean supports(Class<?> arg0) {
		return true;
	}
	
}

CustomLogoutHandler.java

	@Autowired
        private XXService XService;

	public void logout(HttpServletRequest request,
			HttpServletResponse response, Authentication authentication) {

		//log out of BO Server
		XService.terminateEnterpriseSession();
		//return the values and log off from spring security as well
		super.logout(request, response, authentication);
	}

applicationContext.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.zkoss.org/2008/zkspring/core http://www.zkoss.org/2008/zkspring/core/zkspring-core.xsd
		http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
        

	<http auto-config="false" entry-point-ref="loginUrlAuthenticationEntryPoint">

		<!-- ZK au has to be accessed anonymously -->
		<intercept-url pattern="/zkau/**" access="IS_AUTHENTICATED_ANONYMOUSLY"
			requires-channel="any" />

		<!-- allowing access to css resources -->
		<intercept-url pattern="/css/**" access="IS_AUTHENTICATED_ANONYMOUSLY"
			requires-channel="any" />
			

		<!-- allowing access to images resources -->
		<intercept-url pattern="/images/**" access="IS_AUTHENTICATED_ANONYMOUSLY"
			requires-channel="any" />

		<!-- allowing access to layout resources -->
		<intercept-url pattern="/layout/**" access="IS_AUTHENTICATED_ANONYMOUSLY"
			requires-channel="any" />

		<!-- allowing access to login page -->
		<intercept-url pattern="/login.zul" access="IS_AUTHENTICATED_ANONYMOUSLY" />
		<intercept-url pattern="/sectest.zul" access="IS_AUTHENTICATED_ANONYMOUSLY" />

		<!-- After defining other resources secure all pages and links -->
		<intercept-url pattern="/**" access="ROLE_USER" />

		<!-- Custom Login Filter -->
		<custom-filter ref="customAuthenticationFilter"
			position="FORM_LOGIN_FILTER" />

		<!-- Custom Logout Filter -->
		<custom-filter ref="customLogoutFilter" position="LOGOUT_FILTER" />
	</http>

	<!-- Custom Authentication Filter -->
	<beans:bean id="customAuthenticationFilter"
		class="com.tugrulaslan.security.CustomAuthenticationFilter">
		<beans:property name="authenticationManager" ref="authenticationManager" />
		<beans:property name="authenticationFailureHandler"
			ref="failureHandler" />
		<beans:property name="authenticationSuccessHandler"
			ref="successHandler" />
	</beans:bean>

	<!-- Custom Authentication Filter -->
	<authentication-manager alias="authenticationManager">
		<authentication-provider ref="customAuthenticationProvider" />
	</authentication-manager>

	<!-- Custom Authentication Provider For details check the regarding class -->
	<beans:bean id="customAuthenticationProvider"
		class="com.tugrulaslan.security.CustomAuthenticationProvider" />

	<!-- Successful login handler -->
	<beans:bean id="successHandler"
		class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler">
		<beans:property name="defaultTargetUrl" value="/index.zul" />
	</beans:bean>

	<!-- Failure login handler -->
	<beans:bean id="failureHandler"
		class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
		<beans:property name="defaultFailureUrl" value="/login.zul?login_error=1" />
	</beans:bean>

	<!-- Custom Logout Handler -->
	<beans:bean id="customLogoutHandler" class="com.tugrulaslan.security.CustomLogoutHandler" />
	<beans:bean id="customLogoutFilter"
		class="org.springframework.security.web.authentication.logout.LogoutFilter">
		<beans:constructor-arg value="/login.zul" />
		<beans:constructor-arg>
			<beans:list>
				<beans:ref bean="customLogoutHandler" />
			</beans:list>
		</beans:constructor-arg>
		<beans:property name="filterProcessesUrl" value="/j_spring_security_logout" />
	</beans:bean>

	<!-- Access Denied Handler -->
	<beans:bean id="accessDeniedHandler"
		class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
		<beans:property name="errorPage" value="/accessDenied.zul" />
	</beans:bean>

	<!-- Customized Login Entry Point -->
	<beans:bean id="loginUrlAuthenticationEntryPoint" scope="prototype"
		class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
		<beans:property name="loginFormUrl" value="/login.zul" />
	</beans:bean>

</beans:beans>

login.zul

<?page title="Login" contentType="text/html;charset=UTF-8"?>
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit"?>
<?variable-resolver class="org.zkoss.zkplus.spring.DelegatingVariableResolver"?>
<zk>
	<div style="width: 700px; margin-left: auto; margin-right: auto;">
		<div height="90px" width="600px"
			style="margin-left: auto; margin-right: auto;">

			
			<label value="Login page"
				style="font-size:16px; font-weight:bold; color:red" />
		</div>
		<window title="User Login Screen" border="normal"
			width="600px">
			<html:form id="loginForm" name="loginForm"
				action="j_spring_security_check" method="POST"
				xmlns:html="native">
				<grid>
					<rows>
						<row>
							<label value="Username" />
							<textbox id="username" name="j_username" width="162px" />
						</row>
						<row>
							<label value="Password" />
							<textbox id="password" type="password"
								name="j_password" width="162px" />
						</row>
						
						<row>
							<label value="Server" />
							<combobox id="server" name="server"
								readonly="true" onCreate="self.setSelectedIndex(0)">
									<comboitem value="SERVER 1"
									label="SERVER 1" />
									<comboitem value="SERVER 2"
									label="SERVER 2" />									
							</combobox>
						</row>
						<row>
							<label />

							<button id="login" type="submit"
								label="Giris" />
						</row>
					</rows>
				</grid>

				<html style="color:red"
					if="${not empty param.login_error}">
					<!-- Here spring failure messages printed -->
			<![CDATA[Hata:
					${SPRING_SECURITY_LAST_EXCEPTION.message} ]]>			
			</html>
			</html:form>
		</window>
	</div>
</zk>