这里给出一个简单的安全验证的实现例子,先说一下需求:

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代码 

  1. <</span> filter >
  2. <</span> filter-name > springSecurityFilterChain </</span> filter-name >
  3. <</span> filter-class > org.springframework.web.filter.DelegatingFilterProxy </</span> filter-class>
  4. </</span> filter >
  5. <</span> filter-mapping >
  6. <</span> filter-name > springSecurityFilterChain </</span> filter-name >
  7. <</span> url-pattern > *.do*" access = "HODLE" />
  8. <</span> logout logout-url = "/logout.do" invalidate-session = "true"
  9. logout-success-url = "/logout.jsp" />
  10. <</span> form-login login-page = "/index.do" default-target-url = "/frame.do"
  11. always-use-default-target = "true" authentication-failure-url = "/index.do?login_error=1" />
  12. <</span> session-management >
  13. <</span> concurrency-control max-sessions = "1" />
  14. </</span> session-management >
  15. </</span> http >
  16. <</span> beans:bean id = "loggerListener"
  17. class = "org.springframework.security.authentication.event.LoggerListener" />
  18. <</span> authentication-manager >
  19. <</span> authentication-provider user-service-ref = "userService" >
  20. <</span> password-encoder hash = "md5" />
  21. </</span> authentication-provider >
  22. </</span> authentication-manager >
  23. <</span> beans:bean id = "userService" class = "com.piaoyi.common.security.UserService" />
  24. <</span> beans:bean id = "accessDecisionManager"
  25. class = "org.springframework.security.access.vote.AffirmativeBased" >
  26. <</span> beans:property name = "decisionVoters" >
  27. <</span> beans:list >
  28. <</span> beans:bean class = "org.springframework.security.access.vote.RoleVoter" />
  29. <</span> beans:bean
  30. class = "org.springframework.security.access.vote.AuthenticatedVoter" />
  31. <</span> beans:bean class = "com.piaoyi.common.security.DynamicRoleVoter" />
  32. </</span> beans:list >
  33. </</span> beans:property >
  34. </</span> beans:bean >
  35. </</span> beans:beans >

UserService.java

Java代码 

  1. public class UserService  implements UserDetailsService{
  2. @Autowired
  3. private ISystemUserService userService;
  4. @Override
  5. public UserDetails loadUserByUsername(String username)
  6. throws UsernameNotFoundException {
  7. // TODO Auto-generated method stub
  8. SystemUser user = userService.findById(username);
  9. if (user ==  null )
  10. throw new UsernameNotFoundException( "The user name " + username
  11. + " can not be found!" );
  12. List resultAuths = new ArrayList();
  13. //增加access中配置的权限,实际上这里就是让所有登陆用户都具备该权限,
  14. //而真正的资源权限验证留给AccessDecisionManager来决定
  15. resultAuths.add(new GrantedAuthorityImpl( "HODLE" ));
  16. //验证用户名和密码是否正确,以及是否权限正确
  17. return new User(username, user.getPassword().toLowerCase(), user.isStatus(),  true ,
  18. true ,  true , resultAuths);
  19. }
  20. }

DynamicRoleVoter.java

Java代码 

  1. public class DynamicRoleVoter  implements
  2. AccessDecisionVoter {
  3. @Autowired
  4. private ISystemUserService userService;
  5. private PathMatcher pathMatcher =  new AntPathMatcher();
  6. @SuppressWarnings ( "unchecked" )
  7. public boolean supports(Class clazz) {
  8. return true ;
  9. }
  10. public boolean supports(ConfigAttribute attribute) {
  11. return true ;
  12. }
  13. public int vote(Authentication authentication, Object object,
  14. java.util.Collection arg2) {
  15. int result = ACCESS_ABSTAIN;
  16. if (!(object  instanceof FilterInvocation))
  17. return result;
  18. FilterInvocation invo = (FilterInvocation) object;
  19. String url = invo.getRequestUrl();//当前请求的URL
  20. Set authorities = null ;
  21. String userId = authentication.getName();
  22. //获得当前用户的可访问资源,自定义的查询方法,之后和当前请求资源进行匹配,成功则放行,否则拦截
  23. authorities = loadUserAuthorities(userService.findById(userId));
  24. Map> urlAuths = authService.getUrlAuthorities();
  25. Set keySet = urlAuths.keySet();
  26. for (String key : keySet) {
  27. boolean matched = pathMatcher.match(key, url);
  28. if (!matched)
  29. continue ;
  30. Set mappedAuths = urlAuths.get(key);
  31. if (contain(authorities, mappedAuths)) {
  32. result = ACCESS_GRANTED;
  33. break ;
  34. }
  35. }
  36. return result;
  37. }
  38. protected boolean contain(Set authorities,
  39. Set mappedAuths) {
  40. if (CollectionUtils.isEmpty(mappedAuths)
  41. || CollectionUtils.isEmpty(authorities))
  42. return false ;
  43. for (GrantedAuthority item : authorities) {
  44. if (mappedAuths.contains(item.getAuthority()))
  45. return true ;
  46. }
  47. return false ;
  48. }

SpringSecurity3.X权限原理(转)的更多相关文章

  1. Android 上SuperUser获取ROOT权限原理解析

    Android 上SuperUser获取ROOT权限原理解析 一. 概述 本文介绍了android中获取root权限的方法以及原理,让大家对android 玩家中常说的“越狱”有一个更深层次的认识. ...

  2. Android 获取ROOT权限原理解析

    一. 概述 本文介绍了android中获取root权限的方法以及原理,让大家对android玩家中常说的“越狱”有一个更深层次的认识. 二. Root的介绍 1.       Root 的目的 可以让 ...

  3. MySQL权限原理及删除MySQL的匿名账户

    MySQL权限系统的工作原理 MySQL权限系统通过下面两个阶段进行认证: (1)对连接的用户进行身份认证,合法的用户通过认证,不合法的用户拒绝连接: (2)对通过认证的合法用户赋予相应的权限,用户可 ...

  4. Sage Crm 权限原理分析

    文字是11年写的,贴出来共享一下,先来一张表结构图: 一.区域.表名:[territories] 1.我们先来看看区域表的结构. 从图中前面都是不能为空的字段,都是很重要的.来介绍一下这些字段: Te ...

  5. 奇特的Local System权限(转载)

    转载自:http://mp.weixin.qq.com/s?__biz=MzA3NTM1MzE4Nw==&mid=202597764&idx=1&sn=0cef1a40fb3c ...

  6. Android权限说明 system权限 root权限

    原文链接:http://blog.csdn.net/rockwupj/article/details/8618655 Android权限说明 Android系统是运行在Linux内核上的,Androi ...

  7. android apk的签名和权限问题

    一. android apk的签名问题(http://blog.csdn.net/lyq8479/article/details/6401093) 1.为什么要给Android应用程序签名?      ...

  8. 学SpringMVC收藏

     一个较完整的SpringMVC工程的配置 2014-01-22 17:17:25 标签:java spring springMVC 配置 springSecurity web.xml 原创作品,允许 ...

  9. DAY6 使用ping钥匙临时开启SSH:22端口,实现远程安全SSH登录管理就这么简单

    设置防火墙策略时,关于SSH:22访问权限,我们常常会设置服务器只接受某个固定IP(如公司IP)访问,但是当我们出差或在家情况需要登录服务器怎么办呢? 常用两种解决方案:1.通过VPN操作登录主机: ...

随机推荐

  1. 视图框架:Spring MVC 4.0(1)

    目录 一.表单标签库 1.1.简介 1.2.常用属性 1.3.form标签与input标签 1.4.checkbox标签 1.5.radiobutton标签 1.6.password标签 1.7.se ...

  2. android线程 Handler Message Queue AsyncTask线程模型 线程交互 + 修改Button样式 示例 最终easy整合版

     首先原谅我把文章的标题写的这么长.其实我还嫌弃它短了因为 写不下去了所以我就不写了.因为我实在不知道该怎么定义这篇文章的标题或许应该叫 "乱谈"比较合适. 这样可能还体现了 ...

  3. Arcgis for Js之featurelayer实现空间查询和属性查询

    空间查询和属性查询是常用的两种对数据的检索与查询方式,在本节,将讲述Arcgis for Js下如何实现featurelayer的这两种查询方式,先贴图给大家看看: 实现界面 属性查询 空间查询 看完 ...

  4. Arcgis for Javascript实现两个地图的联动

    今天在看天地图的时候,有一个多时相的地图显示功能,感觉很好玩,作为技术控的我晚上十点下班到家便是快十一点了,本来应该是睡觉了,但是,激动地心情不能平静,哎,算了,本着不熬夜的程序员不是好程序员的原则, ...

  5. linux 系统统计目录下文件夹的大小

    du -ah --max-depth=1     这个是我想要的结果  a表示显示目录下所有的文件和文件夹(不含子目录),h表示以人类能看懂的方式,max-depth表示目录的深度. du命令用来查看 ...

  6. predis的使用

    predis是PHP连接Redis的操作库,由于它完全使用php编写,大量使用命名空间以及闭包等功能,只支持php5.3以上版本,故实测性能一般,每秒25000次读写. 将session数据存放到re ...

  7. gatsbyjs 了解

    1.  模型 2. 总结&&资料 从模型上可以看出和jamstack 提出的架构模型比较相似,可以看成是一个具体的实现,功能还是比较强大的 https://www.gatsbyjs.o ...

  8. openfaas 安装(docker swarm 模式)

     备注:为了简单使用的是docker-compose 进行组件的安装  预备环境:    docker  (配置好 swarm  集群模式)  docker-compose     1. docker ...

  9. .NET系统框架

    本书是一本讲解.NET技术的书籍,目标读者群也是在.NET框架(.NET Framework)下进行开发的程序员,因此我们无法回避的问题就是:什么是.NET框架?它包含了哪些内容?为开发程序提供了哪些 ...

  10. 遍历listmap 遍历map

    package excel; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import j ...