新的項目沒有開始于是抽空做一個通用一些的
Security,
后來又考慮到
CAS
和
SSL
的認證問題俺還沒有弄懂,就選擇直接使用
Spring
的子項目
acegi
acegi
是基于
Spring
的的一個安全框架,支持
HTTP
基本(
basic
)驗證、
HTTP Request Session
驗證、安全通道、
ACL
等等,功能強大。配置比較簡單,但是還是要寫一下:
1.??
下載
Spring Acegi
的
jar
文件和它的源代碼,在它的
binary
包中有一個
contacts.war
,這個是
acegi
的示例,把它放在
tomcat
的
webapps
下直接運行即可,這個是
acegi
很好的參考。
2.??
將
acegi
的
Http Servlet Filter
配置在
web.xml
中。
???
<!-- Acegi Security-->
???
<
filter
>
??????
<
filter-name
>
Acegi Filter Chain Proxy
</
filter-name
>
??????
<
filter-class
>
org.acegisecurity.util.FilterToBeanProxy
</
filter-class
>
??????
<
init-param
>
??????????
<
param-name
>
targetClass
</
param-name
>
??????????
<
param-value
>
org.acegisecurity.util.FilterChainProxy
</
param-value
>
??????
</
init-param
>
???
</
filter
>
?
???
<
filter-mapping
>
??????
<
filter-name
>
Acegi Filter Chain Proxy
</
filter-name
>
??????
<
url-pattern
>
/*
</
url-pattern
>
???
</
filter-mapping
>
3.??
將
contract
示例下的
applicationContext-acegi-security.xml
放在
ClassPath
下或
WEB-INF
下,并且在
web.xml
中指出該文件的位置:
<
context-param
>
??????
<
param-name
>
contextConfigLocation
</
param-name
>
??????
<
param-value
>
?????? classpath*:/net/chinasam/common/applicationContext-*.xml
??????
/WEB-INF/ applicationContext-acegi-security.xml
</
param-value
>
???
</
context-param
>
4.??
在
applicationContext-acegi-security.xml
中找到下面的
bean
定義
<
bean
id
=
"jdbcDaoImpl"
class
=
"org.acegisecurity.userdetails.jdbc.JdbcDaoImpl"
>
??????
<
property
name
=
"dataSource"
>
??????????
<
ref
bean
=
"dataSource"
/>
??????
</
property
>
???
</
bean
>
可以看到
dataSource
屬性必須引用一個
DataSource
,
修改這個
bean
,
是之使用一個
Spring
管理的
DataSource
實例。
JdbcDaoImpl
是查詢數據庫的實現類,這個類使用下面的
SQL
進行查詢:
"SELECT username,password,enabled FROM users WHERE username = ?";
"SELECT username,authority FROM authorities WHERE username = ?";
前者查詢用戶,后者查詢角色,你可以根據實際項目的情況進行修改:設置
JdbcDaoImpl
的
authoritiesByUsernameQuery
和
usersByUsernameQuery
屬性。
這個我沒有設置過,因為我的數據庫結構和這個一樣。
Acegi
沒有包含用戶管理,關于
User
的
CRUD
你必須自己完成,然后通過這兩個屬性告訴
acegi
如何查詢用戶和角色。
???
5.??
密碼編碼,經常需要給密碼進行編碼,常用的算法包括
MD5
,
SHA
等,
applectionContext –acegi-Security.xml
中的配置為:
<
bean
id
=
"passwordEncoder"
class
=
"org.acegisecurity.providers.encoding.Md5PasswordEncoder"
/>
?
注意,如果使用上述配置,數據庫中的
password
字段內容必須是實際內容的
MD5
摘要。
6.??
ApplicationContext-acegi-securtiy.xml
缺省的使用
HTTP Request
驗證,也就是通過普通的
HTML
標單提交用戶名和口令,所以你必須編寫自己的
login
頁面,以下是一個例子,注意黑體字部分:
<
form
name
=
"login_form"
action
=
"
<
c:url
value
=
'j_acegi_security_check'
/>
"
method
=
"POST"
>
<
table
width
=
"241"
border
=
"0"
cellpadding
=
"0"
cellspacing
=
"0"
align
=
"center"
>
?
<
tr
>
???
<
td
><
img
src
=
"
<
fmt:message
key
=
"login.title.img"
/>
"
width
=
"241"
height
=
"26"
></
td
>
?
</
tr
>
?
<
tr
>
?
<
td
>
?
?
??
<
table
width
=
"241"
align
=
"center"
cellpadding
=
"0"
cellspacing
=
"0"
>
???
?
???
?
<
tr
>
??????
<
td
width
=
"1"
bgcolor
=
"#D2DBE8"
></
td
>
??????
<
td
align
=
"left"
>
<
fmt:message
key
=
"username"
/></
td
>
??????
<
td?
align
=
"left"
>
??????
<
input
type
=
"text"
class
=
"text"
name
=
"j_username"
>
</
td
>
??????
<
td
rowspan
=
"4"
>
??????
<
img
src
=
"
<
fmt:message
key
=
"login.button.img"
/>
"
onclick
=
"javascript:login_form.submit()"
style
=
"cursor:hand"
>
??????
</
td
>
??????
<
td
width
=
"1"
bgcolor
=
"#D2DBE8"
></
td
>
???
?
</
tr
>
???
?
<
tr
>
??????
<
td
width
=
"1"
bgcolor
=
"#D2DBE8"
></
td
>
??????
<
td
align
=
"left"
>
<
fmt:message
key
=
"password"
/></
td
>
??????
<
td
align
=
"left"
>
<
input
type
=
"password"
class
=
"text"
name
=
"j_password"
>
</
td
>
??????
<
td
width
=
"1"
bgcolor
=
"#D2DBE8"
></
td
>
???
?
<
tr
>
??????
<
td
width
=
"1"
bgcolor
=
"#D2DBE8"
></
td
>
??????
<
td
align
=
"left"
colspan
=
"3"
>
<
fmt:message
key
=
"rememberme"
/>
??????
<
input
type
=
"checkbox"
name
=
"_acegi_security_remember_me"
>
</
td
>
??????
<
td
width
=
"1"
bgcolor
=
"#D2DBE8"
></
td
>
???
?
</
tr
>
???
?
</
table
>
?
</
td
></
tr
>
?
<
c:if
test
=
"
${! empty param.login_error}">
?????
<
tr
><
td
><
br
>
?????
<
fmt:message
key
=
"login.failed"
/>
<%=
((AuthenticationException) session.getAttribute(AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY)).getMessage()
%>
?????
</
td
>
??
</
tr
>
?
</
c:if
>
??
</
table
>
?
</
form
>
最后,你需要配置
URL
權限,關于
POJO
的方法權限俺還沒有弄懂,而且,如果不提供遠程訪問的情況下,一般來說也不需要。在
ApplicationContext-acegi-securtiy.xml
找到
bean
:
filterInvocationInterceptor
?
這個是基于
Http Request
驗證的權限
terceptor
,
注意設置
bjectDefinitionSource
屬性,下面是例子,
URL
的格式是參考
ANT
的格式,也可以根據正則表達式的寫法:
<
property
name
=
"objectDefinitionSource"
>
??????????
<
value
>
??????????
<![CDATA[
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/index.faces=ROLE_SUPERVISOR,ROLE_ANONYMOUS,ROLE_USER
/login.jsp*=ROLE_SUPERVISOR,ROLE_ANONYMOUS,ROLE_USER
/images/*.*=ROLE_SUPERVISOR,ROLE_ANONYMOUS,ROLE_USER
/common/*.*=ROLE_SUPERVISOR,ROLE_ANONYMOUS,ROLE_USER
/styles/*.*=ROLE_SUPERVISOR,ROLE_ANONYMOUS,ROLE_USER
/**=ROLE_USER
?????????????
]]>
??????????
</
value
>
各個權限入口的順序十分重要,注意必須把特殊的
URL
權限寫在一般的
URL
權限之前。
?
7. Acegi
1.0
是基于
JDK1.5
的,雖然你可以在
1
.4
下使用,但是我還是把我的項目改為
JDK1
.5,
沒成想還出現了一些問題。另外
JSTL
的也不同了,如果你想使用
EL
,則必須這樣引用
core
:
<%@
taglib
uri
=
"http://java.sun.com/jstl/core_rt"
prefix
=
"c"
%>
在
JDK1.4
下使用
String.replaceFirst
和
replaceAll
方法沒有問題,但是在
JDK1.5
下卻報
IllegalArgumentException
,
getMessage
指出
Illegal group arguments
,但是單獨寫測試類運行卻沒有任何問題,我只好些了自己的
replace
算法,可是總覺得應該使用
JDK
提供的,希望達人指教。
8
.關于如何使用
ACL
、
SSL
等驗證,俺需要進一步研究。