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 :
- Spring 4.1.3.RELEASE
- Spring Security 4.1.3.RELEASE
- Eclipse Neon.1 Release (4.6.1)
- JDK 1.8
- Maven 3
- Tomcat 7
Cấu trúc thư mục và file sẽ như thế này.
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 :
- Nếu URL = /welcome or / thì trả về hello page.
- 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
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.
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
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
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 :
- Spring 4.3.3.RELEASE
- Spring Security 4.1.3.RELEASE
- Eclipse Neon.1 Release (4.6.1)
- JDK 1.8
- Maven 3
- Tomcat 7
Cấu trúc thư mục và file sẽ như thế này.
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