javascript
spring之使用Spring Security实现权限管理
轉載:http://hanqunfeng.iteye.com/blog/1155226
目錄
SpringSecurity3.X--一個簡單實現
SpringSecurity3.X--前臺與后臺登錄認證
SpringSecurity3.X--remember-me
SpringSecurity3.X--驗證碼
作者對springsecurity研究不深,算是個初學者吧,最近很不完整的看了一下翻譯的很是生硬的《Spring3Security-3.0.1中文官方文檔.pdf》,為了便于學習和記憶,所以將所學知識在此記錄下來。
這里給出一個簡單的安全驗證的實現例子,先說一下需求:
1.通過登錄頁面進行登錄
2.用戶登錄前訪問被保護的地址時自動跳轉到登錄頁面
3.用戶信息存儲在數據表中
4.用戶權限信息存在在數據表中
5.用戶登錄成功后訪問沒有權限訪問的地址時跳轉到登錄頁面
?
ok,以上就是一個基本的需求了,大部分的系統都是基于該需求實現登錄模塊的。
?
給出實現之前,先簡單說明一下springsecurity的原理,
1.AccessDecisionManager
和我們一般實現登錄驗證采用filter的方式一樣,springsecurity也是一個過濾器,當請求被springsecurity攔截后,會先對用戶請求的資源進行安全認證,如果用戶有權訪問該資源,則放行,否則將阻斷用戶請求或提供用戶登錄,
在springsecurity中,負責對用戶的請求資源進行安全認證的是AccessDecisionManager,它就是一組投票器的集合,默認的策略是使用一個AffirmativeBased,既只要有一個投票器通過驗證就允許用戶訪問,
所以如果希望實現自己的權限驗證策略,實現自己的投票器是一個很好的選擇。
?
2.UserDetailsService
如果用戶沒有登錄就訪問某一個受保護的資源,則springsecurity會提示用戶登錄,用戶登錄后,由UserDetailsService來驗證用戶是否合法,既驗證用戶名和密碼是否正確,同時驗證用戶是否具備相應的資源權限,
即對應的access的value。
如果用戶驗證通過,則由AccessDecisionManager來決定是否用戶可以訪問該資源。
?
下面給出具體實現:
web.xml
基本上都是這樣配置,就不廢話了。
Xml代碼?
<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> applicationContext-security.xml
<?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/security"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"xmlns:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:tool="http://www.springframework.org/schema/tool" xmlns:beans="http://www.springframework.org/schema/beans"xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsdhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsdhttp://www.springframework.org/schema/tool http://www.springframework.org/schema/tool/spring-tool-3.0.xsdhttp://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"default-lazy-init="true"><!-- 不需要進行認證的資源,3.0之后才改為這樣配置 --><http security="none" pattern="/index.do" /><!-- 因為要使用自己的權限驗證規則,所以這里要配置access-decision-manager-ref實際上,我只是在accessDecisionManager中增加了一個投票器,其它的屬性都比較簡單,不多說了 --><http auto-config='true' access-decision-manager-ref="accessDecisionManager"access-denied-page="/index.do"><intercept-url pattern="/demo.do*" access="IS_AUTHENTICATED_REMEMBERED" /><intercept-url pattern="/**/*.do*" access="HODLE" /><logout logout-url="/logout.do" invalidate-session="true"logout-success-url="/logout.jsp" /><form-login login-page="/index.do" default-target-url="/frame.do"always-use-default-target="true" authentication-failure-url="/index.do?login_error=1" /><session-management><concurrency-control max-sessions="1" /></session-management></http><!-- Automatically receives AuthenticationEvent messages --><beans:bean id="loggerListener"class="org.springframework.security.authentication.event.LoggerListener" /><!-- 認證管理器,使用自定義的UserDetailsService,并對密碼采用md5加密--><authentication-manager><authentication-provider user-service-ref="userService"><password-encoder hash="md5" /></authentication-provider></authentication-manager><beans:bean id="userService" class="com.piaoyi.common.security.UserService" /><!-- 訪問決策管理器,這里使用AffirmativeBased,并加入一個自定義的投票器DynamicRoleVoter --><beans:bean id="accessDecisionManager"class="org.springframework.security.access.vote.AffirmativeBased"><beans:property name="decisionVoters"><beans:list><beans:bean class="org.springframework.security.access.vote.RoleVoter" /><beans:beanclass="org.springframework.security.access.vote.AuthenticatedVoter" /><beans:bean class="com.piaoyi.common.security.DynamicRoleVoter" /></beans:list></beans:property></beans:bean> </beans:beans>
UserService.java
?
Java代碼?? public class UserService implements UserDetailsService{@Autowiredprivate ISystemUserService userService;@Overridepublic UserDetails loadUserByUsername(String username)throws UsernameNotFoundException {// TODO Auto-generated method stubSystemUser user = userService.findById(username); if (user == null)throw new UsernameNotFoundException("The user name " + username+ " can not be found!");List<GrantedAuthority> resultAuths = new ArrayList<SystemAuthority>();//增加access中配置的權限,實際上這里就是讓所有登陸用戶都具備該權限,//而真正的資源權限驗證留給AccessDecisionManager來決定resultAuths.add(new GrantedAuthorityImpl("HODLE"));//驗證用戶名和密碼是否正確,以及是否權限正確return new User(username, user.getPassword().toLowerCase(), user.isStatus(), true,true, true, resultAuths);} }DynamicRoleVoter.java
Java代碼 public class DynamicRoleVoter implements AccessDecisionVoter { @Autowired private ISystemUserService userService; private PathMatcher pathMatcher = new AntPathMatcher(); /* * (non-Javadoc) * * @see * org.springframework.security.vote.AccessDecisionVoter#supports(java.lang * .Class) */ @SuppressWarnings("unchecked") public boolean supports(Class clazz) { return true; } /* * (non-Javadoc) * * @seeorg.springframework.security.vote.AccessDecisionVoter#supports(org. * springframework.security.ConfigAttribute) */ public boolean supports(ConfigAttribute attribute) { return true; } /* * (non-Javadoc) * * @seeorg.springframework.security.vote.AccessDecisionVoter#vote(org. * springframework.security.Authentication, java.lang.Object, * org.springframework.security.ConfigAttributeDefinition) */ public int vote(Authentication authentication, Object object, java.util.Collection arg2) { int result = ACCESS_ABSTAIN; if (!(object instanceof FilterInvocation)) return result; FilterInvocation invo = (FilterInvocation) object; String url = invo.getRequestUrl();//當前請求的URL Set<GrantedAuthority> authorities = null; String userId = authentication.getName(); //獲得當前用戶的可訪問資源,自定義的查詢方法,之后和當前請求資源進行匹配,成功則放行,否則攔截 authorities = loadUserAuthorities(userService.findById(userId)); Map<String, Set<String>> urlAuths = authService.getUrlAuthorities(); Set<String> keySet = urlAuths.keySet(); for (String key : keySet) { boolean matched = pathMatcher.match(key, url); if (!matched) continue; Set<String> mappedAuths = urlAuths.get(key); if (contain(authorities, mappedAuths)) { result = ACCESS_GRANTED; break; } } return result; } protected boolean contain(Set<GrantedAuthority> authorities, Set<String> mappedAuths) { if (CollectionUtils.isEmpty(mappedAuths) || CollectionUtils.isEmpty(authorities)) return false; for (GrantedAuthority item : authorities) { if (mappedAuths.contains(item.getAuthority())) return true; } return false; } }總結
以上是生活随笔為你收集整理的spring之使用Spring Security实现权限管理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hibernate之悲观锁与乐观锁
- 下一篇: Spring AOP 本质