01-Spring Security框架學習
01-Spring Security框架學習
簡介
Spring Security 是什麼
Spring Security 為基於 Java EE 的企業應用提供綜合的安全服務。尤其支援使用Spring Framework構建的專案,這是目前企業軟體開發的流行的Java EE解決方案。
Spring Security 解決那些問題
Java EE Servlet 規範或 EJB 規範的安全特性在典型的企業應用場景中缺乏深度;在系統環境中做大量的重複配置工作(例:判斷使用者是否登入,是否具備管理員的許可權等)。
一般來說,Web 應用的安全性包括使用者認證(Authentication)和使用者授權(Authorization)兩個部分。使用者認證指的是驗證某個使用者是否為系統中的合法主體,也就是說使用者能否訪問該系統。使用者認證一般要求使用者提供使用者名稱和密碼。系統通過校驗使用者名稱和密碼來完成認證過程。使用者授權指的是驗證某個使用者是否有許可權執行某個操作。在一個系統中,不同使用者所具有的許可權是不同的。比如對一個檔案來說,有的使用者只能進行讀取,而有的使用者可以進行修改。一般來說,系統會為不同的使用者分配不同的角色,而每個角色則對應一系列的許可權。這些概念非常通用,它們並不是 Spring Security 的特性。
Spring Security 的優點
認證級別
在認證級別,Spring Security 支援範圍廣泛的認證模型。大多數認證模型由第三方提供,或由相關標準制定組織(如 IETF)研製,同時Spring Security 提供它自己的認證功能。
- HTTP BASIC headers認證 (基於IETF RFC標準)
- HTTP Digest headers認證 (基於IETF RFC標準)
- HTTP X.509 客戶端證書交換 (基於IETF RFC標準)
- LDAP (一種非常常見的跨平臺認證需求,在大環境下尤甚)
- 基於表單的認證 (通常用於簡單的使用者需求)
- OpenID認證
- 基於預定義的請求頭進行認證 (諸如計算機叢集)
- JA-SIG 中央認證服務 (也稱為CAS, 是一種流行的開源的單點登陸系統)
- 為RMI 和 HttpInvoker(一種Spring遠端協議)提供對使用者透明的認證機制
- 自動的 “remember-me” 認證 (你可以勾選此選項,從而避免在一定時間內進行重複認證)
- 匿名認證 (為每個未經認證的使用者提供一個特殊的安全身份)
- Run-as 認證 (同一個呼叫需要進行不同的安全校驗時非常有用)
- Java認證與認證服務 - Java Authentication and Authorization Service (JAAS)
- JEE
- 認證 (如果你需要,你仍然可以使用容器託管
- 認證)
- Kerberos
- Java開源單點登陸 - Java Open Source Single Sign On (JOSSO) *
- OpenNMS網路管理平臺 - OpenNMS Network Management Platform *
- AppFuse *
- AndroMDA *
- Mule ESB *
- Direct Web Request (DWR) *
- Grails *
- Tapestry *
- JTrac *
- Jasypt *
- Roller *
- Elastic Path *
- Atlassian Crowd *
- 你自己的許可權系統 (參見後續內容)
帶*表示由第三方提供
授權功能
Spring Security允許對授權功能進行深度設定。它關注於三個主要方面:web請求授權、方法呼叫授權以及域物件例項訪問授權
歷史背景
- 2004年1月,已經大約有20人在使用此程式碼。這些首批使用者開始建議將其作為一個SourceForge專案,於是專案於2004年3月正式成立。
- 2006年5月,1.0.0 final release版本正式釋出
- 2007年年末的時候,正式成為Spring Portfolio官方專案,並更名為”Spring Security”。
…
Spring Security版本編號 MAJOR.MINOR.PATCH(主版本.小版本.補丁)
- MAJOR的變更意味著大規模的API的更新,因此很多地方都不會相容舊版本。
- MINOR的變更儘可能保持原始碼和編譯檔案的相容性,儘管可能有一些設計上的變更或者不相容的更新。
- PATCH通常完全向前向後相容,主要用於修復一些bug與缺陷。
Spring Security 的入門案例
基本步驟
- 建立Maven的web專案,在pom.xml中匯入依賴入下
<!-- spring-security 的依賴 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.version}</version>
</dependency>
- web.xml 配置過濾器
<!-- 通過 ContextLoaderListener 定義 spring context 容器的xml檔案的位置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/*.xml
</param-value>
</context-param>
<!-- springSecurity 指定的過濾器:springSecurityFilterChain(該過濾鏈過濾所有的連線) -->
<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>
<!-- web容器(監聽器)啟動載入容器上下文-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
- 建立用於演示的頁面,
src/main/webapp/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
spring-security,hello world!
歡迎來到,spring-security的世界!
</body>
</html>
- 新增Spring Security 的配置檔案
<?xml version="1.0" encoding="UTF-8"?>
<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.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<!-- 頁面的連結規則 -->
<http use-expressions="false">
<intercept-url pattern="/**" access="ROLE_ADMIN"/>
<!-- 開啟表單提交功能 -->
<form-login/>
</http>
<!-- 認證管理器 -->
<authentication-manager>
<authentication-provider>
<user-service>
<user name="admin" password="admin" authorities="ROLE_ADMIN"/>
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
注意:該檔案是本案例的重點,基本內容使用註釋。
- 把security的頭資訊的配置作為了預設配置,那麼以後在進行編寫security的相關配置的時候就不需要字首。
執行效果
出現問題解決
出現
java.lang.NoSuchMethodError: org.springframework.util.AntPathMatcher.setCaseSensitive(Z)V
的錯誤,如下詳細錯誤資訊Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.web.DefaultSecurityFilterChain#0': Cannot resolve reference to bean 'org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#0' while setting constructor argument with key [4]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#0': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter]: Constructor threw exception; nested exception is java.lang.NoSuchMethodError: org.springframework.util.AntPathMatcher.setCaseSensitive(Z)V at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359) at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108) at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveManagedList(BeanDefinitionValueResolver.java:382) at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:157) at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:637) at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:140) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1131) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1034) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351) ... 26 more Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#0': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter]: Constructor threw exception; nested exception is java.lang.NoSuchMethodError: org.springframework.util.AntPathMatcher.setCaseSensitive(Z)V at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1093) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1038) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351) ... 40 more Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter]: Constructor threw exception; nested exception is java.lang.NoSuchMethodError: org.springframework.util.AntPathMatcher.setCaseSensitive(Z)V at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:163) at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:89) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1086) ... 48 more Caused by: java.lang.NoSuchMethodError: org.springframework.util.AntPathMatcher.setCaseSensitive(Z)V at org.springframework.security.web.util.matcher.AntPathRequestMatcher$SpringAntMatcher.createMatcher(AntPathRequestMatcher.java:268) at org.springframework.security.web.util.matcher.AntPathRequestMatcher$SpringAntMatcher.<init>(AntPathRequestMatcher.java:252) at org.springframework.security.web.util.matcher.AntPathRequestMatcher$SpringAntMatcher.<init>(AntPathRequestMatcher.java:245) at org.springframework.security.web.util.matcher.AntPathRequestMatcher.<init>(AntPathRequestMatcher.java:116) at org.springframework.security.web.util.matcher.AntPathRequestMatcher.<init>(AntPathRequestMatcher.java:84) at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.<init>(UsernamePasswordAuthenticationFilter.java:62) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:147) ... 50 more
問題原因分析:
由於
AntPathMatcher
的類的方法在setCaseSensitive()
在Spring-core 4.1.X 中不存在導致.
參考答案:問題解決方式
修改Spring和Spring Security的版本到4.2.3.RELEASE
。
專案
[專案剛剛開始,後期上傳至Git倉庫共享]
參考資料
- Spring Security 參考手冊 Gitbook
- spring security中文教程講解 轉自 臨遠 部落格