spring之使用Spring Security实现权限管理

来源:互联网 发布:js高级程序设计最新 编辑:程序博客网 时间:2024/06/05 08:11

转载: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;      }  }  






0 0
原创粉丝点击