一、spring security的模塊
搭建spring security首先我們要導入必須的jar,即maven的依賴。spring security按模塊划分,一個模塊對應一個jar。
spring security分為以下九個模塊:
1.Core spring-security-core.jar:核心模塊。包含核心的認證(authentication)和授權(authorization)的類和接口,遠程支持和基礎配置API。
2.Remoting spring-security-remoting.jar:提供與spring remoting整合的支持。
3.Web spring-security-web.jar:包含過濾器和相關的網絡安全的代碼。用於我們進行web安全驗證和基於URL的訪問控制。
4.Config spring-security-config.jar:包含security namepace的解析代碼。
5.LDAP spring-security-ldap.jar:提供LDAP驗證和配置的支持。
6.ACL spring-security-acl.jar:提供對特定domain對象的ACL(訪問控制列表)實現。用來限定對特定對象的訪問
7.CAS sprig-security-cas.jar:提供與spring security CAS客戶端集成
8.OpenID spring-security-openid.jar:提供OpenId Web驗證支持。基於一個外部OpenId服務器對用戶進行驗證。
9.Test spring-security-test.jar:提供spring security的測試支持。
一般情況下,Core和Config模塊都是需要的,因為我們本教程只是用於Java web應用表單的驗證登錄,所以這里我們還需要引入Web。
說明:本篇教程的代碼已上傳github,地址:https://github.com/wutianqi/spring_security_create
二、搭建
1.項目工程結構
2.代碼展示
2.1 pom.xml
<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>com.wuqi</groupId> <artifactId>spring_security_create</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>spring_security_create Maven Webapp</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <!-- web --> <jsp.version>2.2</jsp.version> <servlet.version>3.1.0</servlet.version> <jstl.version>1.2</jstl.version> <!-- spring 和 spring security --> <spring-security.version>4.2.3.RELEASE</spring-security.version> <spring-framework.version>4.3.11.RELEASE</spring-framework.version> <!-- Logging --> <logback.version>1.0.13</logback.version> <slf4j.version>1.7.5</slf4j.version> </properties> <dependencies> <!-- spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring-framework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring-framework.version}</version> </dependency> <!-- spring security --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-core</artifactId> <version>${spring-security.version}</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>${spring-security.version}</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>${spring-security.version}</version> </dependency> <!-- 其他一些依賴 --> <dependency> <groupId>javax</groupId> <artifactId>javaee-web-api</artifactId> <version>7.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlet.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>${jstl.version}</version> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>${jsp.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> <version>2.5.3</version> </dependency> <!-- 日志 --> <!-- 使用SLF4J和LogBack作為日志 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.16</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>${slf4j.version}</version> </dependency> <!--logback日志--> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>${logback.version}</version> </dependency> <!--實現slf4j接口並整合--> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-access</artifactId> <version>${logback.version}</version> </dependency> </dependencies> <build> <finalName>spring_security_create</finalName> <plugins> <!-- 配置maven的內嵌的tomcat,通過內置的tomcat啟動 --> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <uriEncoding>utf8</uriEncoding> <!-- 配置啟動的端口為9090 --> <port>9090</port> <path>/</path> </configuration> </plugin> </plugins> </build> </project>
該pom文件除了包括了spring security的依賴外,還包括了spring、springmvc、日志的一些依賴,除了spring security的依賴,其他的你沒必要太過於糾結。直接拿過來用就可以了。日志我使用了logback,這個你也直接拿過來用就行了,直接將logback.xml放在你的類路徑下就可以起作用了。而且這些知識也不是本篇教程所討論的。
2.2 MyWebConfig
package com.wuqi.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.JstlView; /** * MVC配置類 * @author wuqi * @date 2018/06/13 */ @EnableWebMvc @Configuration @ComponentScan("com.wuqi") public class MyWebConfig extends WebMvcConfigurerAdapter { //配置mvc視圖解析器 @Bean public InternalResourceViewResolver viewResolver() { InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setPrefix("/WEB-INF/classes/views/"); viewResolver.setSuffix(".jsp"); viewResolver.setViewClass(JstlView.class); return viewResolver; } }
MyWebConfig是SpringMvc的配置類,這里只配置了視圖解析器
2.3 WebInitializer
package com.wuqi.config; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; /** * 替代web.xml的配置 * @author wuqi * @date 2018/06/13 */ public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return null; } @Override protected Class<?>[] getServletConfigClasses() { return new Class[] {MyWebConfig.class}; } @Override protected String[] getServletMappings() { //將DispatcherServlet映射到 / return new String[] {"/"}; } }
WebInitializer相當於在web.xml中注冊DispatcherServlet,以及配置Spring Mvc的配置文件
2.4 MySecurityConfig
package com.wuqi.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.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; /** * spring security配置類 * @author wuqi * @date 2018/06/13 */ @EnableWebSecurity @Configuration public class MySecurityConfig extends WebSecurityConfigurerAdapter { @Autowired public void configUser(AuthenticationManagerBuilder builder) throws Exception { builder .inMemoryAuthentication() //創建用戶名為user,密碼為password的用戶 .withUser("user").password("password").roles("USER"); } }
MySecurityConfig是spring security的配置類,定制spring security的一些行為就在這里。其中@EnableWebSecurity用於創建過濾器
2.5 SecurityInitializer
package com.wuqi.config; import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; /** * security初始化類,用戶注冊過濾器 * @author wuqi * @date 2018/06/13 */ public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer { }
SecurityInitializer主要就是用於注冊spring secuirty的過濾器
2.6 logback.xml
<?xml version="1.0" encoding="UTF-8"?> <configuration scan="true" scanPeriod="1 seconds"> <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator"> <resetJUL>true</resetJUL> </contextListener> <jmxConfigurator /> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>logbak: %d{HH:mm:ss.SSS} %logger{36} - %msg%n</pattern> </encoder> </appender> <logger name="org.springframework.security.web" level="DEBUG" /> <logger name="org.springframework.security" level="DEBUG" /> <logger name="org.springframework.security.config" level="DEBUG" /> <root level="INFO"> <appender-ref ref="console" /> </root> </configuration>
該日志文件就是將web、core、config模塊的日志級別調為debug模式。
3.運行展示
3.1 通過maven內置的Tomcat啟動項目(不知道的網上看下,有很多資料),訪問端口為9090。地址欄訪問 http://localhost:9090
由此可以看到當訪問我們的項目時,spring security將我們的項目保護了起來,並提供了一個默認的登錄頁面,讓我們去登錄。我們在MySecurityConfig中配置了一個用戶。用戶名為"user",密碼為"password",輸入這個用戶名和密碼,即可正常訪問我們的項目。
3.2 輸入用戶名和密碼
三、總結
到現在為止,我們已經搭建了一個基於spring(spring mvc)的spring security項目。可能你會很疑惑,為什么會產生這種效果。那個輸入用戶名和密碼的頁面,我們在項目中也沒有創建,是怎么出來的呢?
其實這一切都是經過我們上述的配置,我們創建並注冊了spring security的過濾器。是這些過濾器為我們做到的。除此之外,spring security還為我們做了額外的其他的保護。總的來說,經過我們上述的配置后,spring security為我們的應用提供了以下默認功能:
1.訪問應用中的每個URL都需要進行驗證
2.生成一個登陸表單
3.允許用戶使用username和password來登陸
4.允許用戶注銷
5.CSRF攻擊攔截
6.Session Fixation(session固定攻擊)
7.安全Header集成
7.1 HTTP Strict Transport Security for secure requests
7.2 X-Content-Type-Options integration
7.3 緩存控制 (can be overridden later by your application to allow caching of your static resources)
7.4 X-XSS-Protection integration
7.5 X-Frame-Options integration to help prevent Clickjacking
8.Integrate with the following Servlet API methods
8.1 HttpServletRequest#getRemoteUser()
8.2 HttpServletRequest.html#getUserPrincipal()
8.3 HttpServletRequest.html#isUserInRole(java.lang.String)
8.4 HttpServletRequest.html#login(java.lang.String, java.lang.String)
8.5 HttpServletRequest.html#logout()
下一節,通過spring security過濾器的創建和注冊源碼的分析,你將會了解這一切!
參考資料:http://www.tianshouzhi.com/api/tutorials/spring_security_4/250
https://docs.spring.io/spring-security/site/docs/4.1.3.RELEASE/reference/htmlsingle/