瀵逛簬涓涓吀鍨嬬殑Web搴旂敤錛屽畬鍠勭殑璁よ瘉鍜屾巿鏉冩満鍒舵槸蹇呬笉鍙皯鐨勶紝鍦⊿pringFramework涓紝Juergen Hoeller鎻愪緵鐨勮寖渚婮PetStore緇欎簡(jiǎn)涓浜涜繖鏂歸潰鐨勪粙緇嶏紝浣嗚繕榪滆繙涓嶅錛孉cegi鏄竴涓笓闂ㄤ負(fù)SpringFramework鎻愪緵瀹夊叏鏈哄埗鐨?欏圭洰錛屽叏縐頒負(fù)Acegi Security System for Spring錛屽綋鍓嶇増鏈負(fù)0.5.1錛屽氨鍏剁洰鍓嶆彁渚涚殑鍔熻兘錛屽簲璇ュ彲浠ユ弧瓚崇粷澶у鏁板簲鐢ㄧ殑闇姹傘?br />
鏈枃鐨勪富瑕佺洰鐨勬槸甯屾湜鑳藉璇存槑濡備綍鍦ㄥ熀浜嶴pring鏋勬灦鐨刉eb搴旂敤涓嬌鐢ˋcegi錛岃屼笉鏄緇嗕粙緇嶅叾涓殑姣忎釜鎺ュ彛銆佹瘡涓被銆傛敞鎰忥紝鍗充嬌瀵瑰凡緇忓瓨鍦ㄧ殑Spring搴旂敤錛岄氳繃涓嬮潰浠嬬粛鐨勬楠わ紝涔熷彲浠ラ┈涓婁韓鍙楀埌Acegi鎻愪緵鐨勮璇佸拰鎺堟潈銆?/font>
[鍩虹宸ヤ綔]
鍦ㄤ綘鐨刉eb搴旂敤鐨刲ib涓坊鍔燗cegi涓嬭澆鍖呬腑鐨刟cegi-security.jar
[web.xml]
瀹炵幇璁よ瘉鍜屾巿鏉冪殑鏈甯哥敤鐨勬柟娉曟槸閫氳繃filter錛孉cegi浜︽槸濡傛錛岄氬父Acegi闇瑕佸湪web.xml娣誨姞浠ヤ笅5涓猣ilter:
<filter>
聽(tīng) <filter-name>Acegi Channel Processing Filter</filter-name>
聽(tīng) <filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
聽(tīng) <init-param>
聽(tīng)聽(tīng)聽(tīng) <param-name>targetClass</param-name>
聽(tīng)聽(tīng)聽(tīng) <param-value>net.sf.acegisecurity.securechannel.ChannelProcessingFilter</param-value>
聽(tīng) </init-param>
</filter>
<filter>
聽(tīng) <filter-name>Acegi Authentication Processing Filter</filter-name>
聽(tīng) <filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
聽(tīng) <init-param>
聽(tīng)聽(tīng)聽(tīng) <param-name>targetClass</param-name>
聽(tīng)聽(tīng)聽(tīng) <param-value>net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter</param-value>
聽(tīng) </init-param>
</filter>
<filter>
聽(tīng) <filter-name>Acegi HTTP BASIC Authorization Filter</filter-name>
聽(tīng) <filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
聽(tīng) <init-param>
聽(tīng)聽(tīng)聽(tīng) <param-name>targetClass</param-name>
聽(tīng)聽(tīng)聽(tīng) <param-value>net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter</param-value>
聽(tīng) </init-param>
</filter>
<filter>
聽(tīng) <filter-name>Acegi Security System for Spring Auto Integration Filter</filter-name>
聽(tīng) <filter-class>net.sf.acegisecurity.ui.AutoIntegrationFilter</filter-class>
</filter>
<filter>
聽(tīng) <filter-name>Acegi HTTP Request Security Filter</filter-name>
聽(tīng) <filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
聽(tīng) <init-param>
聽(tīng)聽(tīng)聽(tīng) <param-name>targetClass</param-name>
聽(tīng)聽(tīng)聽(tīng) <param-value>net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter</param-value>
聽(tīng) </init-param>
</filter>
鏈鍏堝紩璧瘋糠鎯戠殑鏄痭et.sf.acegisecurity.util.FilterToBeanProxy錛孉cegi鑷繁鐨勬枃妗d笂瑙i噴鏄細(xì) 鈥淲hat聽(tīng) FilterToBeanProxy does is delegate the Filter's methods through to a bean which is obtained from the
Spring application context. This enables the bean to benefit from the Spring application context lifecycle support and configuration flexibility.鈥濓紝濡傚笇鏈涙繁絀剁殑璇濓紝鍘葷湅鐪嬫簮浠g爜搴旇涓嶉毦鐞嗚В銆?br />
鍐嶄笅鏉ュ氨鏄坊鍔爁ilter-mapping浜?jiǎn)锛?xì)
<filter-mapping>
聽(tīng) <filter-name>Acegi Channel Processing Filter</filter-name>
聽(tīng) <url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
聽(tīng) <filter-name>Acegi Authentication Processing Filter</filter-name>
聽(tīng) <url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
聽(tīng) <filter-name>Acegi HTTP BASIC Authorization Filter</filter-name>
聽(tīng) <url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
聽(tīng) <filter-name>Acegi Security System for Spring Auto Integration Filter</filter-name>
聽(tīng) <url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
聽(tīng) <filter-name>Acegi HTTP Request Security Filter</filter-name>
聽(tīng) <url-pattern>/*</url-pattern>
</filter-mapping>
榪欓噷錛岄渶瑕佹敞鎰忎互涓嬩袱鐐癸細(xì)
1) 榪欏嚑涓猣ilter鐨勯『搴忔槸涓嶈兘鏇存敼鐨勶紝欏哄簭涓嶅灝嗘棤娉曟甯稿伐浣滐紱
2) 濡傛灉浣犵殑搴旂敤涓嶉渶瑕佸畨鍏ㄤ紶杈擄紝濡俬ttps錛屽垯灝?Acegi Channel Processing Filter"鐩稿叧鍐呭娉ㄩ噴鎺夊嵆鍙紱
3) 濡傛灉浣犵殑搴旂敤涓嶉渶瑕丼pring鎻愪緵鐨勮繙紼嬭闂満鍒訛紝濡侶essian and Burlap錛屽皢"Acegi HTTP BASIC Authorization
Filter"鐩稿叧鍐呭娉ㄩ噴鎺夊嵆鍙?br />
[applicationContext.xml]
鎺ヤ笅鏉ュ氨鏄娣誨姞applicationContext.xml涓殑鍐呭浜?jiǎn)锛屼粠鍒氭墠FilterToBeanFactory鐨勮В閲婂彲浠ョ湅鍑猴紝鐪熸鐨刦ilter閮?br />鍦⊿pring鐨刟pplicationContext涓鐞嗭細(xì)
1) 棣栧厛錛屼綘鐨勬暟鎹簱涓繀欏誨叿鏈変繚瀛樼敤鎴峰悕鍜屽瘑鐮佺殑table錛孉cegi瑕佹眰table鐨剆chema蹇呴』濡備笅錛?br />
CREATE TABLE users (
聽(tīng)聽(tīng) 聽(tīng)username VARCHAR(50) NOT NULL PRIMARY KEY,
聽(tīng)聽(tīng) 聽(tīng)password VARCHAR(50) NOT NULL,
聽(tīng)聽(tīng) 聽(tīng)enabled BIT NOT NULL
);
CREATE TABLE authorities (
聽(tīng)聽(tīng) 聽(tīng)username VARCHAR(50) NOT NULL,
聽(tīng)聽(tīng) 聽(tīng)authority VARCHAR(50) NOT NULL
);
CREATE UNIQUE INDEX ix_auth_username ON authorities ( username, authority );
ALTER TABLE authorities ADD CONSTRAINT fk_authorities_users foreign key (username) REFERENCES users
(username);
2) 娣誨姞璁塊棶浣犵殑鏁版嵁搴撶殑datasource鍜孉cegi鐨刯dbcDao錛屽涓嬶細(xì)
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
聽(tīng) <property name="driverClassName"><value>${jdbc.driverClassName}</value></property>
聽(tīng) <property name="url"><value>${jdbc.url}</value></property>
聽(tīng) <property name="username"><value>${jdbc.username}</value></property>
聽(tīng) <property name="password"><value>${jdbc.password}</value></property>
</bean>
<bean id="jdbcDaoImpl" class="net.sf.acegisecurity.providers.dao.jdbc.JdbcDaoImpl">
聽(tīng) <property name="dataSource"><ref bean="dataSource"/></property>
</bean>
3) 娣誨姞DaoAuthenticationProvider:
<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
聽(tīng) <property name="authenticationDao"><ref bean="authenticationDao"/></property>
聽(tīng) <property name="userCache"><ref bean="userCache"/></property>
</bean>
<bean id="userCache" class="net.sf.acegisecurity.providers.dao.cache.EhCacheBasedUserCache">
聽(tīng) <property name="minutesToIdle"><value>5</value></property>
</bean>
濡傛灉浣犻渶瑕佸瀵嗙爜鍔犲瘑錛屽垯鍦╠aoAuthenticationProvider涓姞鍏ワ細(xì)<property name="passwordEncoder"><ref
bean="passwordEncoder"/></property>錛孉cegi鎻愪緵浜?jiǎn)鍑牽U嶅姞瀵嗘柟娉曪紝璇︾粏鎯呭喌鍙湅鍖?br />net.sf.acegisecurity.providers.encoding
4) 娣誨姞authenticationManager:
<bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager">
聽(tīng) <property name="providers">
聽(tīng)聽(tīng)聽(tīng) <list>
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng) <ref bean="daoAuthenticationProvider"/>
聽(tīng)聽(tīng)聽(tīng) </list>
聽(tīng)聽(tīng) </property>
</bean>
5) 娣誨姞accessDecisionManager:
<bean id="accessDecisionManager" class="net.sf.acegisecurity.vote.AffirmativeBased">
聽(tīng) <property name="allowIfAllAbstainDecisions">
聽(tīng)聽(tīng)聽(tīng) <value>false</value>
聽(tīng) </property>
聽(tīng) <property name="decisionVoters">
聽(tīng)聽(tīng)聽(tīng) <list><ref bean="roleVoter"/></list>
聽(tīng) </property>
</bean>
<bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/>
6) 娣誨姞authenticationProcessingFilterEntryPoint:
<bean id="authenticationProcessingFilterEntryPoint"
class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
聽(tīng) <property name="loginFormUrl"><value>/acegilogin.jsp</value></property>
聽(tīng) <property name="forceHttps"><value>false</value></property>
</bean>
鍏朵腑acegilogin.jsp鏄櫥闄嗛〉闈紝涓涓渶綆鍗曠殑鐧誨綍欏甸潰濡備笅錛?br />
<%@ taglib prefix='c' uri='http://java.sun.com/jstl/core' %>
<%@ page import="net.sf.acegisecurity.ui.AbstractProcessingFilter" %>
<%@ page import="net.sf.acegisecurity.AuthenticationException" %>
<html>
聽(tīng) <head>
聽(tīng)聽(tīng)聽(tīng) <title>Login</title>
聽(tīng) </head>
聽(tīng) <body>
聽(tīng)聽(tīng)聽(tīng) <h1>Login</h1>
聽(tīng)聽(tīng)聽(tīng) <form action="<c:url value='j_acegi_security_check'/>" method="POST">
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng) <table>
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng) <tr><td>User:</td><td><input type='text' name='j_username'></td></tr>
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng) <tr><td>Password:</td><td><input type='password' name='j_password'></td></tr>
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng) <tr><td colspan='2'><input name="submit" type="submit"></td></tr>
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng) <tr><td colspan='2'><input name="reset" type="reset"></td></tr>
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng) </table>
聽(tīng)聽(tīng)聽(tīng) </form>
聽(tīng) </body>
</html>
7) 娣誨姞filterInvocationInterceptor:
<bean id="filterInvocationInterceptor"
class="net.sf.acegisecurity.intercept.web.FilterSecurityInterceptor">
聽(tīng) <property name="authenticationManager">
聽(tīng)聽(tīng)聽(tīng) <ref bean="authenticationManager"/>
聽(tīng) </property>
聽(tīng) <property name="accessDecisionManager">
聽(tīng)聽(tīng)聽(tīng) <ref bean="accessDecisionManager"/>
聽(tīng) </property>
聽(tīng) <property name="objectDefinitionSource">
聽(tīng)聽(tīng)聽(tīng) <value>
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng) CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng) \A/sec/administrator.*\Z=ROLE_SUPERVISOR
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng) \A/sec/user.*\Z=ROLE_TELLER
聽(tīng)聽(tīng)聽(tīng) </value>
聽(tīng) </property>
</bean>
榪欓噷璇鋒敞鎰忥紝瑕乷bjectDefinitionSource涓畾涔夊摢浜涢〉闈㈤渶瑕佹潈闄愯闂紝闇瑕佹牴鎹嚜宸辯殑搴旂敤闇姹傝繘琛屼慨鏀癸紝鎴戜笂闈㈢粰鍑?br />鐨勫畾涔夌殑鎰忔濇槸榪欐牱鐨勶細(xì)
聽(tīng)a. CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON鎰忔濇槸鍦ㄦ瘮杈冭姹傝礬寰勬椂鍏ㄩ儴杞崲涓哄皬鍐?br />聽(tīng)b. \A/sec/administrator.*\Z=ROLE_SUPERVISOR鎰忔濇槸鍙湁鏉冮檺涓篟OLE_SUPERVISOR鎵嶈兘璁塊棶/sec/administrator*鐨勯〉闈?br />聽(tīng)c. \A/sec/user.*\Z=ROLE_TELLER鎰忔濇槸鍙湁鏉冮檺涓篟OLE_TELLER鐨勭敤鎴鋒墠鑳借闂?sec/user*鐨勯〉闈?br />
8) 娣誨姞securityEnforcementFilter:
<bean id="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter">
聽(tīng) <property name="filterSecurityInterceptor">
聽(tīng)聽(tīng)聽(tīng) <ref bean="filterInvocationInterceptor"/>
聽(tīng) </property>
聽(tīng) <property name="authenticationEntryPoint">
聽(tīng)聽(tīng)聽(tīng) <ref bean="authenticationProcessingFilterEntryPoint"/>
聽(tīng) </property>
</bean>
9) 娣誨姞authenticationProcessingFilter:
<bean id="authenticationProcessingFilter"
class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
聽(tīng) <property name="authenticationManager">
聽(tīng)聽(tīng)聽(tīng) <ref bean="authenticationManager"/>
聽(tīng) </property>
聽(tīng) <property name="authenticationFailureUrl">
聽(tīng)聽(tīng)聽(tīng) <value>/loginerror.jsp</value>
聽(tīng) </property>
聽(tīng) <property name="defaultTargetUrl">
聽(tīng)聽(tīng)聽(tīng) <value>/</value>
聽(tīng) </property>
聽(tīng) <property name="filterProcessesUrl">
聽(tīng)聽(tīng)聽(tīng) <value>/j_acegi_security_check</value>
聽(tīng) </property>
</bean>
鍏朵腑authenticationFailureUrl鏄璇佸け璐ョ殑欏甸潰銆?br />
10) 濡傛灉闇瑕佷竴浜涢〉闈㈤氳繃瀹夊叏閫氶亾鐨勮瘽錛屾坊鍔犱笅闈㈢殑閰嶇疆:
<bean id="channelProcessingFilter" class="net.sf.acegisecurity.securechannel.ChannelProcessingFilter">
聽(tīng) <property name="channelDecisionManager">
聽(tīng)聽(tīng)聽(tīng) <ref bean="channelDecisionManager"/>
聽(tīng) </property>
聽(tīng) <property name="filterInvocationDefinitionSource">
聽(tīng)聽(tīng)聽(tīng) <value>
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng) CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng) \A/sec/administrator.*\Z=REQUIRES_SECURE_CHANNEL
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng) \A/acegilogin.jsp.*\Z=REQUIRES_SECURE_CHANNEL
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng) \A/j_acegi_security_check.*\Z=REQUIRES_SECURE_CHANNEL
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng) \A.*\Z=REQUIRES_INSECURE_CHANNEL
聽(tīng)聽(tīng)聽(tīng) </value>
聽(tīng) </property>
</bean>
<bean id="channelDecisionManager" class="net.sf.acegisecurity.securechannel.ChannelDecisionManagerImpl">
聽(tīng) <property name="channelProcessors">
聽(tīng)聽(tīng)聽(tīng) <list>
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng) <ref bean="secureChannelProcessor"/>
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng) <ref bean="insecureChannelProcessor"/>
聽(tīng)聽(tīng)聽(tīng) </list>
聽(tīng) </property>
</bean>
<bean id="secureChannelProcessor" class="net.sf.acegisecurity.securechannel.SecureChannelProcessor"/>
<bean id="insecureChannelProcessor" class="net.sf.acegisecurity.securechannel.InsecureChannelProcessor"/>
[緙哄皯浜?jiǎn)浠涔堬紵]
Acegi鐩墠鎻愪緵浜?jiǎn)涓たU?secure object"錛屽垎鍒欏甸潰鍜屾柟娉曡繘琛屽畨鍏ㄨ璇佺鐞嗭紝鎴戣繖閲屼粙緇嶇殑鍙槸鍒╃敤
FilterSecurityInterceptor瀵硅闂〉闈㈢殑鏉冮檺鎺у埗錛岄櫎姝や箣澶栵紝Acegi榪樻彁渚涗簡(jiǎn)鍙﹀涓涓狪nterceptor鈥斺?br />MethodSecurityInterceptor錛屽畠緇撳悎runAsManager鍙疄鐜板瀵硅薄涓殑鏂規(guī)硶鐨勬潈闄愭帶鍒訛紝浣跨敤鏂規(guī)硶鍙弬鐪婣cegi鑷甫鐨勬枃妗?br />鍜宑ontact鑼冧緥銆?br />
[鏈鍚庤璇寸殑]
鏈潵浠ヤ負(fù)鍙槸璇存槑濡備綍浣跨敤Acegi鑰屽凡錛屽簲璇ラ潪甯哥畝鍗曪紝浣嗙湡姝e啓璧鋒潵鎵嶅彂鐜版兂瑕佹潯鐞嗘竻妤氱殑鐞嗛『鎵鏈夐渶瑕佺殑bean榪樻槸寰?br />鍥伴毦鐨勶紝浣嗘効鎴戞病鏈夐仐婕忓お澶氫笢瑗匡紝濡傛灉鎴戠殑鏂囩珷鏈変粈涔堥仐婕忔垨閿欒鐨勮瘽錛岃繕璇峰弬鐪婣cegi鑷甫鐨剄uick-start鑼冧緥錛屼絾璇?br />娉ㄦ剰錛岃繖涓寖渚嬫槸涓嶈兘鐩存帴鎷挎潵鐢ㄧ殑銆?/font>