go to  ForumEasy.com   
JavaPro  
 
 
   Home  |  MyForum  |  FAQ  |  Archive    You are not logged in. [Login] or [Register]  
Forum Home » Web Design & Implementation » Spring Security
Email To Friend  |   Set Alert To This Topic Rewarding Points Availabe: 0 (What's this) New Topic  |   Post Reply
Author Topic: Spring Security
WebSpider
member
offline   
 
posts: 147
joined: 06/29/2006
from: Seattle, WA
  posted on: 11/23/2017 02:42:43 AM    Edit  |   Quote  |   Report 
Spring Security
Introduction

Spring Security provides security services for J2EE-based enterprise software applications.


Prerequsites

  • Eclipse with Spring Tools Suite (STS) -- link
  • Dependencies (pom.xml):
    	<dependencies>
    		<!-- Spring -->
    		<!-- ... other dependency elements ... -->
    		<dependency>
    		    <groupId>org.springframework.security</groupId>
    		    <artifactId>spring-security-web</artifactId>
    		    <version>4.2.3.RELEASE</version>
    		</dependency>
    		<dependency>
    		    <groupId>org.springframework.security</groupId>
    		    <artifactId>spring-security-config</artifactId>
    		    <version>4.2.3.RELEASE</version>
    		</dependency>
    		<dependency> <!-- optional,  LDAP related -->
    		    <groupId>org.springframework.security</groupId>
    		    <artifactId>spring-security-ldap</artifactId>
    		    <version>4.2.3.RELEASE</version>
    		</dependency>				
    	</dependencies>
    


  •  Profile | Reply Points Earned: 0
    WebSpider
    member
    offline   
     
    posts: 147
    joined: 06/29/2006
    from: Seattle, WA
      posted on: 11/23/2017 02:48:14 AM    Edit  |   Quote  |   Report 
    Spring Security -- Configuration
    /WEB-INF/spring/spring-security.xml

    Example #1: Role based + In-Memory authentication
    	<!-- AUTHORIZATION -->
    	<http pattern="/img/**" security="none" />
    
    	<http auto-config="true">
    		<intercept-url pattern="/admin/*" access="ROLE_ADMIN" />
    		<intercept-url pattern="/app/**/*" access="ROLE_USER" />
    	</http>
    
    	<!-- AUTHENTICATION (in memory) -->
    	<authentication-manager>
    	  <authentication-provider>
    	    <user-service>
    		<user name="john" password="john_pass" authorities="ROLE_USER" />
    		<user name="lisa" password="lisa_pass" authorities="ROLE_USER, ROLE_ADMIN" />
    	    </user-service>
    	  </authentication-provider>
    	</authentication-manager>
    


    Example #2: Expression-Based Access Control + LDAP authentication
    	<!-- AUTHORIZATION -->
    	<http pattern="/img/*" security="none" />
    
    	<http auto-config="true" use-expressions="true">
    		<intercept-url pattern="/img/*" access="permitAll" />
    		<intercept-url pattern="/app/**/*" access="isAuthenticated()" />
    		<intercept-url pattern="/**/*" access="permitAll" />
    	</http>
    
    	<!-- AUTHENTICATION (LDAP) -->
    	<authentication-manager>
    	    <authentication-provider ref="ldapActiveDirectoryAuthProvider"></authentication-provider>
    	</authentication-manager>
    
    	<beans:bean id="ldapActiveDirectoryAuthProvider"
    class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
    	    <beans:constructor-arg value="abc.xyz.com"></beans:constructor-arg>
    	    <beans:constructor-arg value="ldaps://ad.abc.xyz.com:636"></beans:constructor-arg>
    	</beans:bean>
    


    The most common built-in expressions:
  • hasRole([role])
  • hasAnyRole([role1,role2])
  • hasAuthority([authority])
  • hasAnyAuthority([authority1,authority2])
  • principal -- allows direct access to the Principal object
  • authentication -- allows direct access to the Authentication object
  • permitAll
  • denyAll
  • isAnonymous()
  • isRememberMe() -- returns true if the current principal is a remember-me user
  • isAuthenticated() -- !isAnonymous()
  • isFullyAuthenticated() -- !(isAnonymous()||isRememberMe())
  • hasPermission(Object target, Object permission) -- hasPermission(domainObject, 'read')
  • hasPermission(Object targetId, String targetType, Object permission) -- hasPermission(1, 'com.example.Message', 'read')

  •  Profile | Reply Points Earned: 0
    WebSpider
    member
    offline   
     
    posts: 147
    joined: 06/29/2006
    from: Seattle, WA
      posted on: 11/23/2017 02:56:46 AM    Edit  |   Quote  |   Report 
    /WEB-INF/web.xml

    	<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
    	<context-param>
    		<param-name>contextConfigLocation</param-name>
    		<param-value>/WEB-INF/spring/*.xml</param-value>
    	</context-param>
    	
    	<!-- LISTENERS -->
    	<!-- Creates the Spring Container shared by all Servlets and Filters -->
    	<listener>
    		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    	</listener>
    
    
    	<!-- FILTERS -->
    	<!-- Creates the Spring Security filters shared by all Servlets and Filters -->
    	<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>	
    
    	<!-- SERVLETS -->
    	<servlet>
    		<servlet-name>myServlet</servlet-name>
    		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    		<init-param>
    			<param-name>contextConfigLocation</param-name>
    			<param-value>/WEB-INF/spring/myServlet/dispatch-servlet.xml</param-value>
    		</init-param>
    		<load-on-startup>1</load-on-startup>
    	</servlet>
    		
    	<servlet-mapping>
    		<servlet-name>myServlet</servlet-name>
    		<url-pattern>/</url-pattern>
    	</servlet-mapping>
    
    


    With the above xml, the Spring Framework will do:
  • Setting a filter which is handled by DelegatingFilterProxy which is going to delegate the job to bean named springSecurityFilterChain
  • springSecurityFilterChain is a built-in default name which is implemented by <security:http> element, injected by spring-security.xml.
  • spring-security.xml is to load via ContextLoaderListener when ServletContext is initialized.

  •  Profile | Reply Points Earned: 0
    WebSpider
    member
    offline   
     
    posts: 147
    joined: 06/29/2006
    from: Seattle, WA
      posted on: 12/06/2017 03:11:24 AM    Edit  |   Quote  |   Report 
    Example #3: Expression-Based Access Control + LDAP authentication + Custom Login Page
    Step 1: Custom login -- Controller

    GET http://<host>:<port>/<context>/my_login --> this.login(String error, String logout)
    	@RequestMapping(value = "/my_login", method = RequestMethod.GET)
    	public ModelAndView login(
    		@RequestParam(value = "error", required = false) String error,
    		@RequestParam(value = "logout", required = false) String logout) {
    
    		ModelAndView model = new ModelAndView();
    		if (error != null) {
    			model.addObject("error", "Invalid username and password!");
    		}
    
    		if (logout != null) {
    			model.addObject("msg", "You've been logged out successfully.");
    		}
    		model.setViewName("login");
    
    		return model;
    
    	}
    


    Step 2: Custom login -- View

    model("login") --> login.jsp
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    <html>
        <body onload='document.loginForm.username.focus();'>
    
    	<h1>Spring Security Custom Login Form (XML)</h1>
    	<div>
    		<h2>Login with Username and Password</h2>
    
    		<c:if test="${not empty error}">
    			<div class="error">${error}</div>
    		</c:if>
    		<c:if test="${not empty msg}">
    			<div class="msg">${msg}</div>
    		</c:if>
    
    		<c:url var="loginProcessUrl" value="/where_to_process_login" />
    		<form name='loginForm' action="${loginProcessUrl}" method='POST'>
    		  <table>
    			<tr>
    			   <td>User:</td>
                               <td><input type='text' name='username' value=''></td>
    			</tr>
    			<tr>
    			   <td>Password:</td>
    			   <td><input type='password' name='password' /></td>
    			</tr>
    			<tr>
    			   <td colspan='2'><input name="submit" type="submit"
    					value="submit" /></td>
    			</tr>
    		  </table>
    
    		  <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
    		</form>
    	</div>
        </body>
    </html>
    



    Step 3: Custom login -- Configure

            
            <!-- AUTHORIZATION -->
    	<http pattern="/img/*" security="none" />
    
    	<http auto-config="true" use-expressions="true">
    		<intercept-url pattern="/img/*" access="permitAll" />
    		<intercept-url pattern="/app/**/*" access="isAuthenticated()" />
    		<intercept-url pattern="/**/*" access="permitAll" />
    
    		<form-login 
                        login-page='/my_login'                         <--1-- How to get here: GET /<context>/my_login
    		    username-parameter="username"                  <----- default "username" 
    		    password-parameter="password"                  <----- default "password" 
    	            login-processing-url="/where_to_process_login" <--2-- where to process?  
    		    authentication-failure-url="/my_login?error"   <--3-- where to go if error? 
    		    default-target-url="/welcome"                  <--4-- where to go if success? 
                        always-use-default-target="false"              <--5-- where to go if success? (true)?
                                                                                     default-target-url|user-target-url
                     />
                                
    		<logout 
                        logout-url="/where_to_process_logout"  <--1-- where to process? 
    		    logout-success-url="/my_login?logout"  <--2-- where to go if success? 
                     />
    	 		
    		<!-- enable csrf protection -->
    		<csrf/>
    
    	</http>
    
    	<!-- AUTHENTICATION (LDAP) -->
    	<authentication-manager>
    	    <authentication-provider ref="ldapActiveDirectoryAuthProvider"></authentication-provider>
    	</authentication-manager>
    
    	<beans:bean id="ldapActiveDirectoryAuthProvider"
    class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
    	    <beans:constructor-arg value="abc.xyz.com"></beans:constructor-arg>
    	    <beans:constructor-arg value="ldaps://ad.abc.xyz.com:636"></beans:constructor-arg>
    	</beans:bean>
    


     Profile | Reply Points Earned: 0
    WebSpider
    member
    offline   
     
    posts: 147
    joined: 06/29/2006
    from: Seattle, WA
      posted on: 12/06/2017 03:17:43 AM    Edit  |   Quote  |   Report 
    Custom login -- Flow

    Ultimate goal: GET /app/list_resource
       user -------------------- /app/list_resource -------------------------------------------------> protected resource
    


    How to reach the goal: GET /app/list_resource
       user --------------- /app/list_resource 
                              |
                              v
                       filter: DelegatingFilterProxy
                              |
                              v
                      <http form-login@login-page: /my_login  (1)
                              |
                              v
                      Controller.login(String error, String logout)
                              |
                              v
                      View: login.jsp         action="/where_"
                           (user's input)  -------------------> match (2) in xml? --no-->  (custom process)
                                                                        |
                                                                       yes
                                                                        |
                                                                        v
                                                        processed by Spring: <authentication-manager>
                                                                        |
                                                                     succeed? --no--> /my_login?error (3)
                                                                        |
                                                                       yes
                                                                        |
                                                                        v
                                        always-use-default-target (5) ==true?  --no--> /app/list_resource -----> protected resource
                                                                        |
                                                                       yes
                                                                        |
                                                                        v
                                                                     /welcome (4)
    
    


     Profile | Reply Points Earned: 0
    WebSpider
    member
    offline   
     
    posts: 147
    joined: 06/29/2006
    from: Seattle, WA
      posted on: 07/10/2020 05:58:47 PM    Edit  |   Quote  |   Report 
    Two ways to provide custom login/authentication

       user --------------- /app/list_resource 
                              |
                              v
                       filter: DelegatingFilterProxy
                              |
                              v
                      <http form-login@login-page: /my_login  (1)
                              |
                              v
                      Controller.login(String error, String logout)
                              |
                              v
                      View: login.jsp         action="/where_?"
                           (user's input)  -------------------> match (2) in xml? --no-->  A: (custom process)
                                                                        |
                                                                       yes
                                                                        |
                                                                        v
                                                        B: processed by Spring: <authentication-manager>
                                                                        |
    


    As shown in the above flow chart, there are two possible routes to process authentication:

    Route A: If "/where_?" in login.jsp does NOT match "/where_to_process_login" in xml configuration, the traffic is going to flow to custom process controller:
    @RequestMapping(value = "/where_to_process_login_custom", method = RequestMethod.POST)
    public ModelAndView login_process(@RequestParam String username, @RequestParam String password, HttpSession session){
    	/* your custom implementation here ... */
    }
    



    Route B: If "/where_?" in login.jsp does match "/where_to_process_login" in xml configuration, the traffic is going to flow to spring process and you can still add your own custom implementation by providing your own autentication-provider:
    @Configuration
    @EnableWebSecurity
    public class DBSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private UserDetailsService userDetailsService; 
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
    	/* http.authorizeRequests.configuration ... */
        }
    	
    	
        // XML counterpart (if not defined here by WebSecurityConfigurerAdapter):
        // 	<authentication-manager>
        //     <authentication-provider ref="customAuthenticationProvider" />
        //  </authentication-manager>
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception 
        {
            auth.authenticationProvider(
    		    getAuthenticationProvider() // <-- your own provider here
    		);  
        }
    
        @Bean 
        public DaoAuthenticationProvider getAuthenticationProvider(){
            DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
            auth.setUserDetailsService(userDetailsService);
            auth.setPasswordEncoder(passwordEncoder());
            return auth;
        }
        
        @Bean
        public BCryptPasswordEncoder passwordEncoder(){
            return new BCryptPasswordEncoder();
        }
        
    }
    


     Profile | Reply Points Earned: 0

     
    Powered by ForumEasy © 2003-2005, All Rights Reserved. | Privacy Policy | Terms of Use
     
    Get your own forum today. It's easy and free.