轉自:http://www.iteye.com/topic/1122629
總論
無疑問的,spring security在怎么保護網頁應用安全上做得很強很周全,但有些地方還是很差強人意,比如對<http/>這個標簽,對auto-config="true"與use-expressions="true"的描述和關系辨析上,就語焉不詳。升級到3.1版本后,居然發現有莫名奇妙的錯誤,比如無法解析'ROLE_ADMIN'這樣的標准配置,或者報:
引用 Field or property cannot be found on object of type 'org.springframework.security.web.access.expression.WebSecurityExpressionRoot'
這樣摸不着頭腦的錯誤。如果有遇到這類問題,一個要仔細看官方文檔,徹底理解use-expressions的含義,比如,
在用use-expressions后,就不能用access="ROLE_USER"這樣的配置了;
而且在3.1之后,如果同時用auto-config='true'和use-expression="true"是不行的,就好比撞了兩面牆,左右不是,這種問題的確是使用spring security這樣的龐然大物時比較令人生畏之處,用好了事情迎刃而解,用不好破敵800自損3000,這是因為安全本身就很復雜,一般只能case by case的實現和解決,也難為了做spring security這群人了。
how to do it?
啃吧,專注深入的學習spring security,從它的手冊tutorial一點點看起。
問題解決:
<http use-expressions="true"> <logout /> <remember-me /> <session-management invalid-session-url="/timeout.jsp"> <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" /> </session-management> <!--下邊的access="xxxxx" 中的屬性加上就報錯不知為知--> <intercept-url pattern="/login.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY" /> <intercept-url pattern="/admin.jsp" access="ROLE_ADMIN" /> <form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?error=true" default-target-url="/" /> </http>
報錯:
java.lang.IllegalArgumentException: Failed to evaluate expression 'IS_AUTHENTICATED_ANONYMOUSLY' at org.springframework.security.access.expression.ExpressionUtils.evaluateAsBoolean(ExpressionUtils.java:13) at org.springframework.security.web.access.expression.WebExpressionVoter.vote(WebExpressionVoter.java:34) at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:50) at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:203) at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:106) at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:112) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:35) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:187) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) at org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:109) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:169) at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237) at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:261) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:581) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447) at java.lang.Thread.run(Thread.java:619) Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Field or property 'IS_AUTHENTICATED_ANONYMOUSLY' cannot be found on object of type 'org.springframework.security.web.access.expression.WebSecurityExpressionRoot' at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:206) at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:71) at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:102) at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:97) at org.springframework.security.access.expression.ExpressionUtils.evaluateAsBoolean(ExpressionUtils.java:11) ... 41 more
解決:
改成access="hasRole('ROLE_USER')"就行了
問題2:
今天發現spring全部進級到3.1了,官方網站說是100%與3.0兼容,當然這指的是spring framework,可能沒有包含spring security。
按照我之前進級的經驗來說,起首xml頭上的xsd文件版本要更新一下,從3.0.xsd改為3.1.xsd
別的,碰到了一個問題就是spring security3.1中不再支撐filter="none"了
比如:
<http use-expression="true" auto-config="true"> <intercept-url pattern="/static/**" filters="none"/> <intercept-url pattern="/security/**" access="hasRole(""ROLE_ADMIN"")" /> <intercept-url pattern="/**" access="hasRole(""ROLE_USER"")"/> <http-basic/> </http> 須要改成: <http pattern="/static/**" security="none"/> <http use-expression="true" auto-config="true"> <intercept-url pattern="/security/**" access="hasRole(""ROLE_ADMIN"")" /> <intercept-url pattern="/**" access="hasRole(""ROLE_USER"")"/> <http-basic/> </http>