Monday, 9 February 2015

Spring Security with Hibernate using Maven - Authentication and Authorization Example

URL: http://www.beingjavaguys.com/2014/08/spring-security-with-hibernate.html


Application-Context.xml:


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

    <context:annotation-config />
    <context:component-scan base-package="com.thingovation.smartcollar.*" />
    <!-- <context:property-placeholder location="database.properties"/> -->
    <context:property-placeholder
        location="classpath*:database.properties,classpath*:mailConfs.properties" />

    <!-- CentOS -->
    <!-- <bean id="jedisConnFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
        p:use-pool="true" p:host-name="${redis.hostname}" p:port="${redis.port}"/> -->

    <!-- Dev Server -->
    <bean id="jedisConnFactory"
        class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
        p:use-pool="true" p:host-name="${redis.hostname}" p:port="${redis.port}"
        p:password="${redis.password}" />

    <!-- Redis Template -->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
        p:connection-factory-ref="jedisConnFactory" />


    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="${mysql.drivername}" />
        <property name="url" value="${mysql.url}" />
        <property name="username" value="${mysql.username}" />
        <property name="password" value="${mysql.password}" />
        <property name="maxWait" value="10" />
        <property name="maxIdle" value="5" />
        <property name="maxActive" value="5000" />
        <property name="validationQuery" value="SELECT 1" />
        <property name="testOnBorrow" value="true" />
        <property name="testOnReturn" value="true" />
        <property name="testWhileIdle" value="true" />
        <property name="timeBetweenEvictionRunsMillis" value="10000" />
        <property name="minEvictableIdleTimeMillis" value="600000" />
    </bean>

    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan" value="com.thingovation.smartcollar.dto" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
            </props>
        </property>
    </bean>

    <bean id="template" class="org.springframework.orm.hibernate3.HibernateTemplate">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <!-- <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="mySessionFactory"/> </bean> <tx:annotation-driven
        transaction-manager="transactionManager"/> -->

    <!-- Spring security -->

    <sec:http auto-config="true" create-session="stateless"
        entry-point-ref="restAuthenticationEntryPoint"

        authentication-manager-ref="authenticationManager">
        <sec:intercept-url pattern="/rest/publicapi/getDogActivityByTagId/*"
            access="ROLE_USER,ROLE_ADMIN" />
        <sec:intercept-url pattern="/rest/publicapi/getMostRecentDogActivity/*"
            access="ROLE_USER,ROLE_ADMIN" />
        <sec:intercept-url pattern="/rest/publicapi/getDogActivitiesByDateRange/**"
            access="ROLE_ADMIN" />
        <sec:intercept-url pattern="/rest/publicapi/getAddress/**"
            access="ROLE_ADMIN" />
        <sec:intercept-url pattern="/rest/publicapi/getTagsNearBy/**"
            access="ROLE_ADMIN" />
        <sec:intercept-url
            pattern="/rest/publicapi/getTagsNearByRadiusSearchOverTime/**"
            access="ROLE_ADMIN" />
        <sec:intercept-url
            pattern="/rest/publicapi/getTagsInGivenAreaByRadiusSearch/**" access="ROLE_ADMIN" />
        <sec:intercept-url pattern="/rest/publicapi/postUserLocation/**"
            access="ROLE_ADMIN" />
        <sec:intercept-url pattern="/rest/publicapi/savePermanentLocations/**"
            access="ROLE_ADMIN" />
        <sec:intercept-url pattern="/rest/publicapi/saveTemporaryVisitedLocations/**"
            access="ROLE_ADMIN" />
        <sec:intercept-url pattern="/rest/publicapi/getCommandResponseStatus/**"
            access="ROLE_ADMIN" />
        <sec:intercept-url pattern="/rest/publicapi/SaveGeofencingCoordinations/**"
            access="ROLE_ADMIN" />
        <sec:intercept-url pattern="/rest/publicapi/getDogActivities/**"
            access="ROLE_ADMIN" />
        <sec:intercept-url pattern="/rest/publicapi/saveDogStatus/**"
            access="ROLE_ADMIN" />
        <sec:intercept-url pattern="/rest/publicapi/saveGigyaId/**"
            access="ROLE_ADMIN" />
        <sec:intercept-url pattern="/rest/publicapi/saveGestureSequences/**"
            access="ROLE_ADMIN" />
        <sec:intercept-url pattern="/rest/publicapi/saveGestureSequencesToTag/**"
            access="ROLE_ADMIN" />
        <sec:intercept-url pattern="/rest/publicapi/tagActivation/**"
            access="ROLE_ADMIN" />
        <sec:intercept-url pattern="/rest/publicapi/userFirstLogin/**"
            access="ROLE_ADMIN" />
        <sec:intercept-url pattern="/rest/publicapi/showEventStatus/**"
            access="ROLE_ADMIN" />
        <sec:form-login authentication-success-handler-ref="mySuccessHandler"
            authentication-failure-handler-ref="myFailureHandler" />
        <sec:logout />
        <sec:http-basic />
    </sec:http>


    <bean id="restAuthenticationEntryPoint"
        class="com.thingovation.smartcollar.security.RestAuthenticationEntryPoint" />
    <bean id="mySuccessHandler"
        class="com.thingovation.smartcollar.security.SavedRequestAwareAuthenticationSuccessHandler" />
    <bean id="myFailureHandler"
        class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler" />
    <!-- Spring Mail -->

    <!-- <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
        <property name="host" value="${smtp.host}" /> <property name="port" value="${smtp.port}"
        /> <property name="username" value="${smtp.authenticationUsername}" /> <property
        name="password" value="${smtp.authenticationPassword}" /> <property name="javaMailProperties">
        <props> <prop key="mail.smtp.auth">true</prop> <prop key="mail.smtp.starttls.enable">true</prop>
        <prop key="mail.smtp.ssl.trust">smtp.gmail.com</prop> </props> </property>
        </bean> -->
   
    <!-- Configure Authentication manager -->
    <bean id="bcrypt"
        class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
        <constructor-arg name="strength" value="11" />
    </bean>
   
    <sec:authentication-manager alias="authenticationManager">
        <sec:authentication-provider>
            <sec:password-encoder ref="bcrypt" />
            <sec:jdbc-user-service data-source-ref="dataSource"
                users-by-username-query="SELECT USERNAME, PASSWORD, ENABLED FROM USERS WHERE USERNAME=?"
                authorities-by-username-query="SELECT US.USERNAME ,UR.ROLENAME FROM USERS US, USER_ROLES UR
                WHERE US.UID = UR.UID AND US.USERNAME =? " />
        </sec:authentication-provider>
    </sec:authentication-manager>

</beans>


Spring-sesurity.xml



<?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:oauth="http://www.springframework.org/schema/security/oauth2"
    xmlns:sec="http://www.springframework.org/schema/security"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- Create client details bean for manage client details from database -->
    <!-- The JdbcClientDetailsService provide default implementation for fetching
        the data from oauth_client_details table Other wise we need to create our
        custom class that Implement ClientDetailsService Interface and override its
        loadClientByClientId method -->
    <bean id="clientDetails"
        class="org.springframework.security.oauth2.provider.client.JdbcClientDetailsService">
        <constructor-arg index="0">
            <ref bean="dataSource" />
        </constructor-arg>
    </bean>

    <!-- Configure Authentication manager -->
    <bean id="passwordEncoder"
        class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
        <constructor-arg name="strength" value="11" />
    </bean>

    <!-- This class is the custom implementation of UserDetailSerive Interface
        that provide by the spring, which we Need to implement and override its method.
        But for Oauth spring provide us ClientDetailsUserDetailsService, which already
        implement UserDetailSerive Interface and override its method. -->
    <bean id="clientDetailsUserService"
        class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
        <constructor-arg ref="clientDetails" />
    </bean>

    <sec:authentication-manager alias="authenticationManager">
        <sec:authentication-provider
            user-service-ref="clientDetailsUserService">
            <sec:password-encoder ref="passwordEncoder" />
        </sec:authentication-provider>
    </sec:authentication-manager>

    <!-- Oauth Token Service Using Database -->
    <!-- The JdbcTokenStore class provide the default implementation from access
        the token from database. If we want to customize the JDBC implementation
        we need to implement TokenStore interface and overrider its methods -->
    <bean id="tokenStore"
        class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore">
        <constructor-arg ref="dataSource" />
    </bean>

    <!-- This the service class which is used to access the function of JdbcTokenStore
        class. This is like MVC structure JdbcTokenStore is Dao layer and DefaultTokenServices
        is service layer -->
    <bean id="tokenServices"
        class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
        <property name="tokenStore" ref="tokenStore" />
        <property name="supportRefreshToken" value="true" />
        <property name="clientDetailsService" ref="clientDetails" />
        <property name="accessTokenValiditySeconds" value="300" />
    </bean>

    <!-- A user approval handler that remembers approval decisions by consulting
        existing tokens -->
    <bean id="oAuth2RequestFactory"
        class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory">
        <constructor-arg ref="clientDetails" />
    </bean>
    <bean id="userApprovalHandler"
        class="org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler">
        <property name="requestFactory" ref="oAuth2RequestFactory" />
        <property name="tokenStore" ref="tokenStore" />
    </bean>

    <!-- Authorization Server Configuration of the server is used to provide
        implementations of the client details service and token services and to enable
        or disable certain aspects of the mechanism globally. -->
    <oauth:authorization-server
        client-details-service-ref="clientDetails" token-services-ref="tokenServices"
        user-approval-handler-ref="userApprovalHandler">
        <oauth:authorization-code />
        <oauth:implicit />
        <oauth:refresh-token />
        <oauth:client-credentials />
        <oauth:password authentication-manager-ref="authenticationManager" />
    </oauth:authorization-server>

    <!-- A Resource Server serves resources that are protected by the OAuth2
        token. Spring OAuth provides a Spring Security authentication filter that
        implements this protection. -->
    <oauth:resource-server id="resourceServerFilter"
        token-services-ref="tokenServices" resource-id="rest_api" />

    <!-- Grants access if only grant (or abstain) votes were received. We can
        protect REST resource methods with JSR-250 annotations such as @RolesAllowed -->
    <bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
        <property name="decisionVoters">
            <list>
                <bean class="org.springframework.security.access.annotation.Jsr250Voter" />
            </list>
        </property>
    </bean>

    <!-- If authentication fails and the caller has asked for a specific content
        type response, this entry point can send one, along with a standard 401 status -->
    <bean id="clientAuthenticationEntryPoint"
        class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
        <property name="realmName" value="Authorization/client" />
        <property name="typeName" value="Basic" />
    </bean>
    <bean id="oauthAccessDeniedHandler"
        class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />

    <!-- Allows clients to authenticate using request parameters if included
        as a security filter. It is recommended by the specification that you permit
        HTTP basic authentication for clients, and not use this filter at all. -->
    <bean id="clientCredentialsTokenEndpointFilter"
        class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
        <property name="authenticationManager" ref="authenticationManager" />
    </bean>

    <bean id="oAuth2ClientContextFilter"
        class="org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter">
    </bean>

    <sec:http pattern="/oauth/token" create-session="stateless"    authentication-manager-ref="authenticationManager">
        <sec:intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_ANONYMOUSLY" />
        <sec:http-basic entry-point-ref="clientAuthenticationEntryPoint" />
        <sec:custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER" />
        <sec:custom-filter ref="oAuth2ClientContextFilter" after="EXCEPTION_TRANSLATION_FILTER    " />
        <sec:access-denied-handler ref="oauthAccessDeniedHandler" />
    </sec:http>

    <sec:http pattern="/**" create-session="never" authentication-manager-ref="authenticationManager">
        <sec:anonymous enabled="false" />
        <sec:intercept-url pattern="/**" method="GET"    access="ROLE_USER" />
        <sec:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
        <sec:http-basic entry-point-ref="oauthAuthenticationEntryPoint" />
        <sec:access-denied-handler ref="oauthAccessDeniedHandler" />
    </sec:http>
   
   
    <bean id="oauthAuthenticationEntryPoint"
        class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
        <property name="realmName" value="Authorization" />
    </bean>
   
</beans>


web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
   
    <display-name>Archetype Created Web Application</display-name>

    <servlet>
            <servlet-name>mvc-dispatcher</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
            <servlet-name>mvc-dispatcher</servlet-name>
            <url-pattern>/</url-pattern>
    </servlet-mapping>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring-security.xml, classpath:applicationContext.xml,/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
    </context-param>
   
    <!-- <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param> -->

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <servlet>
        <servlet-name>jersey-serlvet</servlet-name>
        <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>com.thingovation.smartcollar.controller</param-value>
        </init-param>
        <init-param>
            <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
            <param-value>true</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>jersey-serlvet</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>

    <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>
   
</web-app>

mvc-dispatcher-servlet.xml













































<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc" 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-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/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">

    <context:component-scan base-package="com.thingovation.smartcollar.controller" />

    <mvc:annotation-driven />

</beans>

No comments:

Post a Comment