Understanding Spring and Spring Security…

Understanding Spring

In Spring 2.0 and later, the @Repository annotation is a marker for any class that fulfills the role or stereotype (also known as Data Access Object or DAO) of a repository. Among the uses of this marker is the automatic translation of exceptions.

Spring 2.5 introduces further stereotype annotations: @Component, @Service, and @Controller. @Component is a generic stereotype for any Spring-managed component. @Repository, @Service, and @Controller are specializations of @Component for more specific use cases, for example, in the persistence, service, and presentation layers, respectively.

Therefore, you can annotate your component classes with @Component, but by annotating them with @Repository, @Service, or @Controller instead, your classes are more properly suited for processing by tools or associating with aspects. For example, these stereotype annotations make ideal targets for pointcuts.

Thus, if you are choosing between using @Component or @Service for your service layer, @Service is clearly the better choice. Similarly, as stated above, @Repository is already supported as a marker for automatic exception translation in your persistence layer.

| Annotation | Meaning |
+————+—————————————————–+
| @Component | generic stereotype for any Spring-managed component |
| @Repository| stereotype for persistence layer |
| @Service | stereotype for service layer |
| @Controller| stereotype for presentation layer (spring-mvc) |

Dispachter Servlet

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">

    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
		<property name="prefix" value="/WEB-INF/jsp/"/>
		<property name="suffix" value=".jsp"/>
	</bean>

	<!--for controller driven architecture-->
    <mvc:annotation-driven />
    
	<!--for Annotation based Transaction-->
    <tx:annotation-driven />

    <context:annotation-config />

	<!--Package for scanning controllers-->
    <context:component-scan base-package="com.test.**.controller,com.test.**.services, com.test.**.model"/>

    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />

	<!--Package for scanning controllers-->
    <mvc:resources location="/resources/" mapping="/resources/**" />
    
	<!--Internationalization Locale configuration where lang is requestparam and its default value is en-->
   
    <bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
        <property name="paramName" value="lang"/>
    </bean>

	<mvc:interceptors>
        <ref bean="localeChangeInterceptor"/>
    </mvc:interceptors>
	
    <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
        <property name="defaultLocale" value="en"/>
    </bean>

	<!--Below bean can be autowired for reading props value. 
		Whereas we can have combo which passes lang values for example it will find [prjlabel_en or prjlabel_in]-->
    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basenames">
            <list>
                <value>/WEB-INF/i18n/prjlabel</value>
                <value>/WEB-INF/i18n/prjmsg</value>
                <value>/prjprops</value>
            </list>
        </property>
        <property name="defaultEncoding" value="UTF-8"/>
    </bean>    
</beans>

Application Context

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:security="http://www.springframework.org/schema/security"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
       http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">

    <bean id="propertyConfigurer"
          class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
          p:location="/project.properties" />
        
    <bean class="org.apache.commons.dbcp.BasicDataSource" id="dataSource" destroy-method="close">
        <property name="driverClassName">
            <value>foo.fooserver.jdbc.FOODriver</value>
        </property>
        <property name="url">
            <value>jdbc:url</value>            
        </property>
        <property name="username">
            <value>username</value>            
        </property>
        <property name="password">
            <value>password</value>            
        </property>
        <property name="maxActive" value="100"/>
        <property name="maxWait" value="10000"/>
        <property name="maxIdle" value="10"/>
    </bean>

    <bean class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" id="sessionFactory" primary="true" >
        <property name="dataSource">
            <ref bean="dataSource"/>
        </property>
		<!--packagesToScan scans all the classes for hibernate(models)-->
        <property name="packagesToScan" value="test.taher.**.model"/>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
                <prop key="current_session_context_class">thread</prop>
                <prop key="hibernate.cache.use_second_level_cache">true</prop>
                <prop key="hibernate.connection.autocommit">true</prop>                
                <prop key="hibernate.max_fetch_depth">5</prop>
                <prop key="hibernate.default_batch_fetch_size">16</prop>
                <prop key="hibernate.jdbc.batch_size">25</prop>
                <prop key="hibernate.jdbc.fetch_size">8</prop>
                <prop key="hibernate.show_sql">false</prop>
                <prop key="hibernate.connection.release_mode">after_statement</prop>
            </props>
        </property>
    </bean>
    
   
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" p:sessionFactory-ref="sessionFactory" />
        
    <bean  class="org.springframework.orm.hibernate3.HibernateTemplate" id="hibernateTemplate">
        <property name="sessionFactory">
            <ref bean="sessionFactory"/>
        </property>
    </bean>

	<!--Spring Security Configuration-->
    <security:http auto-config="true" >
        <security:intercept-url pattern="/School/" access="IS_AUTHENTICATED_ANONYMOUSLY" />
        <security:intercept-url pattern="/common/**" access="ROLE_TEACHER,ROLE_CLERK,ROLE_STUDENTS" />
                                
        <security:intercept-url pattern="/clerk/**" access="ROLE_CLERK" />
        <security:intercept-url pattern="/teacher/**" access="ROLE_TEACHER"  />
		<security:intercept-url pattern="/students/**" access="ROLE_STUDENTS"  />
               
		<!--default-target-url is a get URL as username password are submitted and checked by springsecurity and than asks for default-url-->
		<!--authentication-failure-handler-ref there is also authentication-failure-url where you can directly specify failure URL if we want some code of 
			execution than we can use handler-->
        <security:form-login login-page="/sessiondead" 
                             login-processing-url="/j_spring_security_check"
                             default-target-url="/viewdisp"
                             always-use-default-target="true"                                      
                             authentication-failure-handler-ref="customAuthenticationFailureHandler"                             
                                      />
        <security:logout logout-success-url="/logout" />

        <security:custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
		<!--We can define UserDefine Filter below one is called after concurrencyFilter-->
        <security:custom-filter after="CONCURRENT_SESSION_FILTER" ref="userDefineFilter" />
        <security:session-management session-authentication-strategy-ref="sas"/>
            
    </security:http>

	<!--Below one authenticates User and assigns Role for User-->
      <security:authentication-manager>
        <security:authentication-provider >
            <security:jdbc-user-service data-source-ref="dataSource"
                                        users-by-username-query="
	          select  emailId username,password,case when(failedAttempt=5) then 'false' else 'true' end  enabled from tbl_PeopleMaster
		      where emailId=?"
                                        authorities-by-username-query="
	         select a.emailId username,b.authority from tbl_PeopleMaster a,tbl_PeopleRoles b
                where a.userId=b.userId
                and a.emailId=?"/>
        </security:authentication-provider>
    </security:authentication-manager>
    
	<!--Login-Failure Filter -->
    <bean id="customAuthenticationFailureHandler" class="com.taher.CustomFilter">
        <constructor-arg type="String" value="loginfailed"></constructor-arg>
        <constructor-arg type="org.hibernate.SessionFactory" ref="sessionFactory"></constructor-arg>              
    </bean> 
        
	<!--Custom UserDefined Filter -->
    <bean id="userDefineFilter" class="com.taher.userDefineFilter">        
        <constructor-arg type="org.hibernate.SessionFactory" ref="sessionFactory"/>        
    </bean> 
    
	<!--Spring Mail Sender-->
    <bean id="JavaMailSender" class ="org.springframework.mail.javamail.JavaMailSenderImpl" >
        <property name="javaMailProperties">
            <props>
                <prop key="mail.smtp.starttls.enable">true</prop>
            </props>
        </property>
    </bean>
   
   <!--3 beans below are for concurrency check and for reading max allowed session from property file-->
    <bean id="concurrencyFilter"
      class="org.springframework.security.web.session.ConcurrentSessionFilter">
        <property name="sessionRegistry" ref="sessionRegistry" />        
    </bean>

    <bean id="sas"
      class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy"
        p:maximumSessions="${max.allowSession}" p:exceptionIfMaximumExceeded="true">
        <constructor-arg name="sessionRegistry" ref="sessionRegistry"/>
    </bean>   
    <bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl"/>
</beans>
import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
/**
 * 
 * @author TaherT
 */
public class CustomFilter extends SimpleUrlAuthenticationFailureHandler {

	// Below properties are set from applicationcontext where defaultFailureUrl=URL on which is to be redirecteted & 
	//sessionFactory if required for DB operations
    private String defaultFailureUrl;      
    private SessionFactory sessionFactory;
    

    public CustomFilter(String defaultFailureUrl,SessionFactory sessionFactory) {
        super();
        this.defaultFailureUrl = defaultFailureUrl;
        this.sessionFactory = sessionFactory;
    }

    @Override
    public void onAuthenticationFailure(HttpServletRequest request,
            HttpServletResponse response, AuthenticationException exception)
            throws IOException, ServletException {
        
        if (exception.getClass().getSimpleName().equals("SessionAuthenticationException")) {
                // It happens when max allowed Sessions for user exceeds                 
        }
        if (exception.getClass().getSimpleName().equals("DisabledException")) {
				// It happens when enabled property of User(Spring calss) get false value
        }
        if (exception.getClass().getSimpleName().equals("BadCredentialsException")) {
				// It happens when either username or password is wrong                 
        }      
        response.sendRedirect(defaultFailureUrl);
    }
}
Advertisements
This entry was posted in Spring and tagged , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s