12/08/2018, 13:57

Hello Spring Security Java Config

Spring framework đã phát triển Spring Security để hỗ trợ cho việc thực hiện cơ chế Authentication và Authorization trên ứng dụng. Bài viết này sẽ hướng dẫn các bạn config Spring Security với demo chức năng login đơn giản. Có 2 cách để config/implement Spring security. Cách thứ nhất là config ...

Spring framework đã phát triển Spring Security để hỗ trợ cho việc thực hiện cơ chế Authentication và Authorization trên ứng dụng.

Bài viết này sẽ hướng dẫn các bạn config Spring Security với demo chức năng login đơn giản.

Có 2 cách để config/implement Spring security. Cách thứ nhất là config bean thông qua file .xml và cách thứ 2 là sử dụng Annotations. Cách thứ 2 - sử dụng Annotations được sử dụng nếu bạn có ý định phát triển project web trong khoảng time dài thì nên chọn cách thứ 2. Cách này còn có ưu điêm là rõ ràng hơn. Ngoài ra cách thứ 2 sử dụng thuần Java.

Nếu bạn đọc nào có ý định tìm hiểu sâu hơn về ưu nhược điêm của 2 cách này thì tham khảo ở preview dưới đây : https://spring.io/blog/2013/07/03/spring-security-java-config-preview-web-security/

Trong phạm vi bài viết này mình sẽ mô tả cả 2 cách config.

Spring Security hello world example

Để build project này mình đã config như sau :

  1. Spring 4.1.3.RELEASE
  2. Spring Security 4.1.3.RELEASE
  3. Eclipse Neon.1 Release (4.6.1)
  4. JDK 1.8
  5. Maven 3
  6. Tomcat 7

Cấu trúc thư mục và file sẽ như thế này.

Screenshot from 2016-10-02 15:17:34.png

Spring Security Dependencies

Để sử dụng được Spring security, bạn cần cài đặt spring-security-web và spring-security-config trong file pom.xml.

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>

         
         
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>

         
         
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.3.1.RELEASE</version>
        </dependency>

         
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.3.1.RELEASE</version>
        </dependency>

         
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.3.1.RELEASE</version>
        </dependency>

		 
	    <dependency>
	        <groupId>org.springframework.security</groupId>
	        <artifactId>spring-security-web</artifactId>
	        <version>4.1.3.RELEASE</version>
	    </dependency>

		 
		<dependency>
		    <groupId>org.springframework.security</groupId>
		    <artifactId>spring-security-config</artifactId>
		    <version>4.1.3.RELEASE</version>
		</dependency>

		 
		<dependency>
		    <groupId>jstl</groupId>
		    <artifactId>jstl</artifactId>
		    <version>1.2</version>
		</dependency>

Spring MVC Web Application

Sau đó là 1 controller đơn giản như dưới :

  1. Nếu URL = /welcome or / thì trả về hello page.
  2. Nếu URL = /admin thì trả về admin page.
package org.o7planning.hellospringmvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class HelloController {

	@RequestMapping(value = { "/", "/welcome**" }, method = RequestMethod.GET)
	public ModelAndView welcomePage() {

		ModelAndView model = new ModelAndView();
		model.addObject("title", "Spring Security Hello World");
		model.addObject("message", "This is welcome page!");
		model.setViewName("hello");
		return model;

	}

	@RequestMapping(value = "/admin**", method = RequestMethod.GET)
	public ModelAndView adminPage() {

		ModelAndView model = new ModelAndView();
		model.addObject("title", "Spring Security Hello World");
		model.addObject("message", "This is protected page!");
		model.setViewName("admin");
		return model;
	}
}

Tiếp đến là các file jsp

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@page session="true"%>
<html>
<body>
	<h1>Title : ${title}</h1>
	<h1>Message : ${message}</h1>

	<c:if test="${pageContext.request.userPrincipal.name != null}">
	   <h2>Welcome : ${pageContext.request.userPrincipal.name}
           | <a href="<c:url value="/j_spring_security_logout" />" > Logout</a></h2>
	</c:if>
</body>
</html>
<%@page session="false"%>
<html>
<body>
	<h1>Title : ${title}</h1>
	<h1>Message : ${message}</h1>
</body>
</html>
<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"
	xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.1.xsd">

	<context:component-scan base-package="org.o7planning.*" />

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

</beans>

Spring Security : User Authentication

Ở đây mình sẽ setting Spring Security ở file 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.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
	http://www.springframework.org/schema/security
	http://www.springframework.org/schema/security/spring-security-4.1.xsd">

	<http auto-config="true">
		<intercept-url pattern="/admin**" access="hasRole ('ROLE_USER')" />
	</http>

	<authentication-manager>
	  <authentication-provider>
	    <user-service>
		<user name="duong" password="123456" authorities="hasRole ('ROLE_USER')" />
	    </user-service>
	  </authentication-provider>
	</authentication-manager>

</beans:beans>

Ở đây, chỉ mỗi user "duong" có thể access vào /admin URL.

Integrate Spring Security

Bạn phải khai báo DelegatingFilterProxy như là một filter servlet trong file web.xml để chặn bất kì request nào đến.

     
    <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>

DEMO

http://localhost:8080/HelloSpringMVC/welcome

Screenshot from 2016-10-02 15:34:24.png

Khi bạn vào trang admin http://localhost:8080/HelloSpringMVC/admin . Spring Security sẽ chuyển bạn về trnag http://localhost:8080/HelloSpringMVC/login và hiển thị form login.

Screenshot from 2016-10-02 15:35:21.png

Nếu username or pwd sai, sẽ có error messages thông báo và Spring sẽ chuyển bạn về đường dẫn http://localhost:8080/HelloSpringMVC/login?error

Screenshot from 2016-10-02 15:36:03.png

Nếu login thành công. Spring sẽ chuyển bạn về request ban đầu của bạn (là request vào trang admin) và hiển thị như sau

Screenshot from 2016-10-02 15:36:47.png

Sample code

https://github.com/duongichi/HelloSpringMVC/tree/SecurityHARDLOGIN

Spring Security Hello World Annotation Example

Phần trước mình đã sử dụng XML để config Spring security. Phần này mình sẽ chuyển các XML đó thành pure Spring annotation.

Để build project này mình đã config như sau :

  1. Spring 4.3.3.RELEASE
  2. Spring Security 4.1.3.RELEASE
  3. Eclipse Neon.1 Release (4.6.1)
  4. JDK 1.8
  5. Maven 3
  6. Tomcat 7

Cấu trúc thư mục và file sẽ như thế này.

Screenshot from 2016-10-02 15:50:14.png

Update pom.xml

Config file pom.xml như dưới đây.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.o7planning</groupId>
  <artifactId>HelloSpringMVC</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>HelloSpringMVC Maven Webapp</name>
  <url>http://maven.apache.org</url>

    <dependencies>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>

         
         
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>

         
         
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-core</artifactId>
		    <version>4.3.3.RELEASE</version>
		</dependency>

         
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>

         
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>

		<dependency>
	        <groupId>org.springframework</groupId>
    	    <artifactId>spring-context</artifactId>
        	<version>4.3.3.RELEASE</version>
    	</dependency>

		 
	    <dependency>
	        <groupId>org.springframework.security</groupId>
	        <artifactId>spring-security-web</artifactId>
	        <version>4.1.3.RELEASE</version>
	    </dependency>

		<dependency>
		    <groupId>org.springframework.security</groupId>
		    <artifactId>spring-security-config</artifactId>
		    <version>4.1.3.RELEASE</version>
		</dependency>

		 
		<dependency>
		    <groupId>jstl</groupId>
		    <artifactId>jstl</artifactId>
		    <version>1.2</version>
		</dependency>

	</dependencies>

    <build>
        <finalName>HelloSpringMVC</finalName>
        <plugins>

             
             
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                 
                 
            </plugin>

            <plugin>
			  <artifactId>maven-war-plugin</artifactId>
			  <version>2.6</version>
			  <configuration>
			    <failOnMissingWebXml>false</failOnMissingWebXml>
			  </configuration>
			</plugin>

        </plugins>
    </build>

</project>

Bạn chú ý là vì mình sẽ không sử dụng web.xml trong lần này nên cần phải khai báo maven-war-plugin. Nếu bạn không khai báo cái này maven build sẽ FAIL.

Spring Security Configuration Class

Bước đầu tiên là add spring security vào application để tạo Spring Security Java Configuration. Config này sẽ tạo nên Servlet Filter - springSecurityFilterChain - chịu trách nhiệm cho việc security (chặng URLs, validation, login form v.v...)

package org.o7planning.hellospringmvc.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("duong").password("abc123").roles("USER");
        auth.inMemoryAuthentication().withUser("admin").password("root123").roles("ADMIN");
        auth.inMemoryAuthentication().withUser("dba").password("root123").roles("ADMIN","DBA");
    }

    @Override
    protected 
                                          
0