zoukankan      html  css  js  c++  java
  • SpringSecurity3.X权限原理(转)

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

    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代码  icon_star[2]

    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代码  sg_trans[1]

    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代码  sg_trans[1][1]

    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. }
  • 相关阅读:
    Django之Form、CSRF、cookie和session
    Django之路由、模板和模型系统
    简约而不简单的Django
    剑指offer(10)矩形覆盖
    剑指offer(9)变态跳台阶
    剑指offer(8)跳台阶
    剑指offer(7)斐波那契数列
    剑指offer(6)旋转数组中的最小数字
    剑指offer(5)用两个栈实现队列
    剑指offer(4)重建二叉树
  • 原文地址:https://www.cnblogs.com/cmzcheng/p/3807339.html
Copyright © 2011-2022 走看看