วิธี Config Spring Security ด้วย Java Class
ก่อนหน้านี้ได้เขียนบทความ Spring Security ที่ Config ด้วยไฟล์ xml ไปแล้ว บทความนี้มาดูวิธีการ Config ด้วย Java Class กันบ้างครับ
ขั้นตอนที่ 1 : สร้างโปรเจ็ค Primefaces + Maven
สามารถดูวิธีการสร้างได้ที่บทความนี้ “สร้างโปรเจ็ค Primefaces ง่ายๆด้วย Netbeans”
ขั้นตอนที่ 2 : สั่งโหลด Library ที่ไฟล์ pom.xml
บทความนี้ใช้ Spring Security เวอร์ชัน 4.2.3 เพิ่ม library 4 ตัวดังนี้
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-core</artifactId> <version>4.2.3.RELEASE</version> </dependency> <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> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency> |
ขั้นตอนที่ 3 : สร้างหน้า Login และหน้า Home
ตัวอย่างนี้ผมจะให้ login ที่หน้า login.xhtml และเมื่อ login ผ่านจะให้แสดงหน้า home.xhtml
login.xhtml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<?xml version='1.0' encoding='UTF-8' ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:c="http://xmlns.jcp.org/jsp/jstl/core" xmlns:fn="http://java.sun.com/jsp/jstl/functions"> <h:head> <title>DEMO Spring Security</title> </h:head> <h:body> <form action="${request.contextPath}/j_spring_security_check" method="post"> <c:if test="${param.error != null}"> <p style="color: red;"> ${fn:replace(SPRING_SECURITY_LAST_EXCEPTION.message, 'org.springframework.security.authentication.BadCredentialsException: ', '')} </p> </c:if> <p> <label for="username">Username</label> <input type="text" id="username" name="username"/> </p> <p> <label for="password">Password</label> <input type="password" id="password" name="password"/> </p> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> <button type="submit" class="btn">Log in</button> </form> </h:body> </html> |
home.xhtml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<?xml version='1.0' encoding='UTF-8' ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html"> <h:head> <title>DEMO Spring Security</title> </h:head> <h:body> <h3>Login Success</h3> <form action="${request.contextPath}/j_spring_security_logout" method="post"> <p> First Name : <h:outputText style="color: #0066ff;" value="#{homeController.user.fname}"/> </p> <p> Last Name : <h:outputText style="color: #0066ff;" value="#{homeController.user.lname}"/> </p> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> <button type="submit" class="btn">Log Out</button> </form> </h:body> </html> |
ขั้นตอนที่ 4 : สร้างคลาส AuthenticationProvider
สำหรับการ Authentication ของ Spring Security นั้นมีอยู่หลายวิธี ในบทความนี้ใช้ AuthenticationProvider ครับ
วิธีการก็คือสร้างคลาสที่ extends AbstractUserDetailsAuthenticationProvider ขึ้นมา แล้วตรวจสอบ user ที่เมธอด retrieveUser ดังนี้
ตัวอย่าง กำหนด user=”user” และ password=”password”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
package com.pacteez.demosecurity.authen; import java.util.ArrayList; import java.util.List; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; public class DemoAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider { @Override protected void additionalAuthenticationChecks(UserDetails ud, UsernamePasswordAuthenticationToken upat) throws AuthenticationException { } @Override protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken upat) throws AuthenticationException { DemoUser user = null; String password = upat.getCredentials().toString(); List<GrantedAuthority> authorities = new ArrayList(); if ("user".equals(username) && "password".equals(password)) { user = new DemoUser(username, password, authorities); user.setFname("Patthanapong"); user.setLname("Pacteez"); } else { throw new BadCredentialsException("Username and password wrong!"); } return user; } } |
ขั้นตอนที่ 5 : สร้างคลาส User
ขั้นตอนนี้ต่อเนื่องจากข้อ 4 หากเราต้องการเก็บค่าของ User เพิ่มเติมก็สามารถสร้างคลาสที่ extends UserDetails ได้ดังนี้
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
package com.pacteez.demosecurity.authen; import java.util.Collection; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.User; public class DemoUser extends User { private String fname; private String lname; public DemoUser(String username, String password, Collection<? extends GrantedAuthority> authorities) { super(username, password, authorities); } public String getFname() { return fname; } public void setFname(String fname) { this.fname = fname; } public String getLname() { return lname; } public void setLname(String lname) { this.lname = lname; } } |
ขั้นตอนที่ 6 : สร้างคลาส WebSecurityConfig
ค่า Config ต่างๆ เราจะกำหนดที่คลาสนี้เลยครับ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
package com.pacteez.demosecurity.authen; import org.springframework.context.annotation.Bean; 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; @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .formLogin() .loginPage("/pages/login.xhtml").permitAll() .loginProcessingUrl("/j_spring_security_check") .defaultSuccessUrl("/pages/home.xhtml") .failureUrl("/pages/login.xhtml?error=1"); http .logout() .logoutUrl("/j_spring_security_logout") .logoutSuccessUrl("/pages/login.xhtml"); http .authorizeRequests() .antMatchers("/javax.faces.resource/**").permitAll() .antMatchers("/pages/**").authenticated(); } @Bean public DemoAuthenticationProvider demoSpringSecurityAuthenticationProvider() { return new DemoAuthenticationProvider(); } } |
ขั้นตอนที่ 7 : สร้างคลาส SecurityWebApplicationInitializer
ส่งคลาสที่ Config เมื่อตะกี๊ไป Initialize ด้วยคลาสนี้
1 2 3 4 5 6 7 8 9 10 |
package com.pacteez.demosecurity.authen; import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer { public SecurityWebApplicationInitializer() { super(WebSecurityConfig.class); } } |
ขั้นตอนที่ 8 : Test โลด!
วิธี Config มีแค่นี้เอง ผมว่าสะดวกและง่ายดายกว่า xml พอสมควรเลยล่ะ
มื่อระบุ Username และ Password ผิด
เมื่อระบุ Username และ Password ถูกต้องจะแสดงหน้า home