zoukankan      html  css  js  c++  java
  • SpringSecurity 自定义用户 角色 资源权限控制

    SpringSecurity 自定义用户 角色 资源权限控制

      1 package com.joyen.learning.security;
      2 
      3 import java.sql.ResultSet;
      4 import java.sql.SQLException;
      5 import java.util.List;
      6 
      7 import org.springframework.context.support.MessageSourceAccessor;
      8 import org.springframework.dao.DataAccessException;
      9 import org.springframework.jdbc.core.RowMapper;
     10 import org.springframework.jdbc.core.support.JdbcDaoSupport;
     11 import org.springframework.security.core.GrantedAuthority;
     12 import org.springframework.security.core.SpringSecurityMessageSource;
     13 import org.springframework.security.core.authority.AuthorityUtils;
     14 import org.springframework.security.core.authority.GrantedAuthorityImpl;
     15 import org.springframework.security.core.userdetails.UserDetails;
     16 import org.springframework.security.core.userdetails.UserDetailsService;
     17 import org.springframework.security.core.userdetails.UsernameNotFoundException;
     18 
     19 /**
     20  * 在这个类中,从数据库中读入用户的密码,角色信息,是否锁定,账号是否过期等
     21  * @author fwj
     22  *
     23  */
     24 public class MyUserDetailService extends JdbcDaoSupport implements UserDetailsService {
     25 
     26     
     27     private String authoritiesByUsernameQuery;
     28     private String usersByUsernameQuery;
     29     
     30     protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
     31     
     32     public UserDetails loadUserByUsername(String username)
     33             throws UsernameNotFoundException, DataAccessException {
     34         List<MyUser> users = loadUsersByUsername(username);
     35         
     36         if (users==null || users.size() == 0) {
     37             logger.debug("Query returned no results for user '" + username + "'");
     38 
     39             throw new UsernameNotFoundException(
     40                     messages.getMessage("JdbcDaoImpl.notFound", new Object[]{username}, "Username {0} not found"), username);
     41         }
     42         
     43         MyUser user = users.get(0);
     44         List<GrantedAuthority> dbAuths = loadUserAuthorities(user.getUsername());
     45         
     46         if (dbAuths == null || dbAuths.size() == 0) {
     47             logger.debug("User '" + username + "' has no authorities and will be treated as 'not found'");
     48 
     49             throw new UsernameNotFoundException(
     50                     messages.getMessage("JdbcDaoImpl.noAuthority",
     51                             new Object[] {username}, "User {0} has no GrantedAuthority"), username);
     52         }
     53         
     54         return createUserDetails(username,user,dbAuths);
     55         
     56     }
     57     
     58     protected List<MyUser> loadUsersByUsername(String username) {
     59         
     60         return getJdbcTemplate().query(usersByUsernameQuery, new String[] {username}, new RowMapper<MyUser>() {
     61             public MyUser mapRow(ResultSet rs, int rowNum) throws SQLException {
     62                 String username = rs.getString(1);
     63                 String password = rs.getString(2);
     64                 String email = rs.getString(3);
     65                 boolean enabled = rs.getBoolean(4);
     66                 return new MyUser(username, password, email, enabled, true, true, true, AuthorityUtils.NO_AUTHORITIES);
     67             }
     68 
     69         });
     70     }
     71     
     72     protected List<GrantedAuthority> loadUserAuthorities(String username) {
     73         return getJdbcTemplate().query(authoritiesByUsernameQuery, new String[] {username}, new RowMapper<GrantedAuthority>() {
     74             public GrantedAuthority mapRow(ResultSet rs, int rowNum) throws SQLException {
     75                 String roleName = rs.getString(2);
     76                 GrantedAuthorityImpl authority = new GrantedAuthorityImpl(roleName);
     77 
     78                 return authority;
     79             }
     80         });
     81     }
     82     
     83     protected UserDetails createUserDetails(String username, MyUser userFromUserQuery,
     84             List<GrantedAuthority> combinedAuthorities) {
     85         String returnUsername = userFromUserQuery.getUsername();
     86 
     87         return new MyUser(returnUsername, userFromUserQuery.getPassword(), userFromUserQuery.getEmail(), userFromUserQuery.isEnabled(),
     88                 true, true, true, combinedAuthorities);
     89     }
     90 
     91     public String getAuthoritiesByUsernameQuery() {
     92         return authoritiesByUsernameQuery;
     93     }
     94 
     95     public void setAuthoritiesByUsernameQuery(String authoritiesByUsernameQuery) {
     96         this.authoritiesByUsernameQuery = authoritiesByUsernameQuery;
     97     }
     98 
     99     public String getUsersByUsernameQuery() {
    100         return usersByUsernameQuery;
    101     }
    102 
    103     public void setUsersByUsernameQuery(String usersByUsernameQuery) {
    104         this.usersByUsernameQuery = usersByUsernameQuery;
    105     }
    106     
    107     
    108 
    109 }
    MyUserDetailService
     1 package com.joyen.learning.security;
     2 
     3 import java.util.Collection;
     4 
     5 import org.springframework.security.core.GrantedAuthority;
     6 import org.springframework.security.core.userdetails.User;
     7 
     8 public class MyUser extends User {
     9 
    10     /**
    11      * 
    12      */
    13     private static final long serialVersionUID = 1L;
    14     private final String email;
    15     
    16     public MyUser(String username, String password, String email, boolean enabled,
    17             boolean accountNonExpired, boolean credentialsNonExpired,
    18             boolean accountNonLocked,
    19             Collection<? extends GrantedAuthority> authorities) {
    20         
    21         super(username, password, enabled, accountNonExpired, credentialsNonExpired,
    22                 accountNonLocked, authorities);
    23         // TODO Auto-generated constructor stub
    24         this.email = email;
    25     }
    26 
    27     public String getEmail() {
    28         return email;
    29     }
    30     
    31 }
    MyUser
     1 package com.joyen.learning.security;
     2 
     3 import java.io.IOException;
     4 
     5 import javax.servlet.Filter;
     6 import javax.servlet.FilterChain;
     7 import javax.servlet.FilterConfig;
     8 import javax.servlet.ServletException;
     9 import javax.servlet.ServletRequest;
    10 import javax.servlet.ServletResponse;
    11 
    12 import org.springframework.security.access.SecurityMetadataSource;
    13 import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
    14 import org.springframework.security.access.intercept.InterceptorStatusToken;
    15 import org.springframework.security.web.FilterInvocation;
    16 import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
    17 
    18 public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {
    19 
    20 
    21     private FilterInvocationSecurityMetadataSource securityMetadataSource;  
    22     
    23     public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
    24         return securityMetadataSource;
    25     }
    26 
    27     public void setSecurityMetadataSource(
    28             FilterInvocationSecurityMetadataSource securityMetadataSource) {
    29         this.securityMetadataSource = securityMetadataSource;
    30     }
    31 
    32     @Override
    33     public Class<? extends Object> getSecureObjectClass() {
    34         return FilterInvocation.class;
    35     }
    36 
    37     @Override
    38     public SecurityMetadataSource obtainSecurityMetadataSource() {
    39         return this.securityMetadataSource;
    40     }
    41 
    42     public void destroy() {
    43         // TODO Auto-generated method stub
    44         
    45     }
    46 
    47     public void doFilter(ServletRequest request, ServletResponse response,
    48             FilterChain chain) throws IOException, ServletException {
    49         FilterInvocation fi = new FilterInvocation(request, response, chain);  
    50         invoke(fi);
    51         
    52     }
    53 
    54     public void init(FilterConfig arg0) throws ServletException {
    55         // TODO Auto-generated method stub
    56         
    57     }
    58     
    59     public void invoke(FilterInvocation fi) throws IOException, ServletException {
    60         InterceptorStatusToken token = super.beforeInvocation(fi);
    61         try {
    62             fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
    63         } finally {
    64            super.afterInvocation(token, null);
    65         }
    66     }
    67 
    68 }
    MyFilterSecurityInterceptor
     1 package com.joyen.learning.security;
     2 
     3 import java.util.Collection;
     4 import java.util.Iterator;
     5 
     6 import org.springframework.security.access.AccessDecisionManager;
     7 import org.springframework.security.access.AccessDeniedException;
     8 import org.springframework.security.access.ConfigAttribute;
     9 import org.springframework.security.access.SecurityConfig;
    10 import org.springframework.security.authentication.InsufficientAuthenticationException;
    11 import org.springframework.security.core.Authentication;
    12 import org.springframework.security.core.GrantedAuthority;
    13 import org.springframework.security.web.FilterInvocation;
    14 
    15 /**
    16  * 决策类
    17  * 如果不存在对该资源的定义,直接放行;否则,如果找到正确的角色,即认为拥有权限,并放行
    18  * @author fwj
    19  *
    20  */
    21 public class MyAccessDecisionManager implements AccessDecisionManager {
    22 
    23     public void decide(Authentication authentication, Object object,
    24             Collection<ConfigAttribute> configAttributes)
    25             throws AccessDeniedException, InsufficientAuthenticationException {
    26         
    27         if(configAttributes == null){
    28             return ;
    29          }
    30          
    31          FilterInvocation fi = (FilterInvocation)object;
    32          System.out.println("=============request url==========="+fi.getRequestUrl());  //object is a URL.
    33          Iterator<ConfigAttribute> ite=configAttributes.iterator();  
    34         while(ite.hasNext()){
    35              ConfigAttribute ca=ite.next();
    36              String needRole=((SecurityConfig)ca).getAttribute();
    37             for(GrantedAuthority ga:authentication.getAuthorities()){
    38                 if(needRole.equals(ga.getAuthority())){  //ga is user's role.  
    39                     return;  
    40                  }  
    41              }  
    42          }  
    43         throw new AccessDeniedException("no right");  
    44 
    45     }
    46 
    47     public boolean supports(ConfigAttribute attribute) {
    48         // TODO Auto-generated method stub
    49         return true;
    50     }
    51 
    52     public boolean supports(Class<?> clazz) {
    53         // TODO Auto-generated method stub
    54         return true;
    55     }
    56 
    57 }
    MyAccessDecisionManager
     1 package com.joyen.learning.security;
     2 
     3 import java.sql.ResultSet;
     4 import java.sql.SQLException;
     5 import java.util.ArrayList;
     6 import java.util.Collection;
     7 import java.util.HashMap;
     8 import java.util.Iterator;
     9 import java.util.List;
    10 import java.util.Map;
    11 
    12 import javax.sql.DataSource;
    13 
    14 import org.springframework.jdbc.core.RowMapper;
    15 import org.springframework.jdbc.core.support.JdbcDaoSupport;
    16 import org.springframework.security.access.ConfigAttribute;
    17 import org.springframework.security.access.SecurityConfig;
    18 import org.springframework.security.web.FilterInvocation;
    19 import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
    20 import org.springframework.security.web.util.AntUrlPathMatcher;
    21 import org.springframework.security.web.util.UrlMatcher;
    22 
    23 /** 
    24 *  
    25 * 此类在初始化时,应该取到所有资源及其对应角色的定义 
    26 *  
    27 * @author fuwenjun 
    28 *  
    29 */  
    30 public class MyInvocationSecurityMetadataSource extends JdbcDaoSupport implements
    31         FilterInvocationSecurityMetadataSource {
    32     
    33     private String resourceQuery;
    34     private UrlMatcher urlMatcher = new AntUrlPathMatcher();
    35     private static Map<String, Collection<ConfigAttribute>> resourceMap = null;
    36 
    37     public MyInvocationSecurityMetadataSource(DataSource dataSource,String resourceQuery) {
    38         this.setDataSource(dataSource);
    39         this.resourceQuery = resourceQuery;
    40         this.loadResourceDefine();
    41     }
    42 
    43     private void loadResourceDefine(){
    44         resourceMap = new HashMap<String, Collection<ConfigAttribute>>();  
    45         List<ResourceRole> list = getJdbcTemplate().query(resourceQuery, new RowMapper<ResourceRole>() {
    46                                         public ResourceRole mapRow(ResultSet rs, int rowNum) throws SQLException {
    47                                             String url = rs.getString(1);
    48                                             String role = rs.getString(2);
    49                                             return new ResourceRole(url, role);
    50                                         }
    51                                     });
    52         ConfigAttribute ca = null;
    53         Collection<ConfigAttribute> cca = null;
    54         for (ResourceRole resourceRole : list) {
    55             if(resourceMap.containsKey(resourceRole.getUrl())){
    56                 ca = new SecurityConfig(resourceRole.getRole());
    57                 resourceMap.get(resourceRole.getUrl()).add(ca);
    58             }else{
    59                 ca = new SecurityConfig(resourceRole.getRole());
    60                 cca = new ArrayList<ConfigAttribute>();//首次创建一个新的configattribute集合
    61                 cca.add(ca);
    62                 resourceMap.put(resourceRole.getUrl(), cca);
    63             }
    64         }
    65         
    66     }
    67     
    68     public Collection<ConfigAttribute> getAttributes(Object object)
    69             throws IllegalArgumentException {
    70        String url = ((FilterInvocation)object).getRequestUrl();  
    71        Iterator<String> ite = resourceMap.keySet().iterator();  
    72        while (ite.hasNext()) {
    73             String resURL = ite.next();  
    74            if (urlMatcher.pathMatchesUrl(url, resURL)) {
    75                return resourceMap.get(resURL);  
    76             }
    77         }
    78        return null;
    79     }
    80 
    81     public Collection<ConfigAttribute> getAllConfigAttributes() {
    82         // TODO Auto-generated method stub
    83         return null;
    84     }
    85 
    86     public boolean supports(Class<?> clazz) {
    87         // TODO Auto-generated method stub
    88         return true;
    89     }
    90     
    91 }
    MyInvocationSecurityMetadataSource
     1 package com.joyen.learning.security;
     2 
     3 public class ResourceRole {
     4 
     5     private String url;
     6     private String role;
     7 
     8     public ResourceRole(String url, String role) {
     9         this.url = url;
    10         this.role = role;
    11     }
    12 
    13     public String getUrl() {
    14         return url;
    15     }
    16 
    17     public String getRole() {
    18         return role;
    19     }
    20 }
    ResourceRole
     1 <?xml version="1.0" encoding="UTF-8"?>  
     2 <beans:beans xmlns="http://www.springframework.org/schema/security"  
     3      xmlns:beans="http://www.springframework.org/schema/beans"  
     4      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
     5      xsi:schemaLocation="http://www.springframework.org/schema/beans  
     6             http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
     7             http://www.springframework.org/schema/security  
     8             http://www.springframework.org/schema/security/spring-security-3.0.xsd">
     9             
    10     <http access-denied-page="/403" auto-config="false"><!-- 当访问被拒绝时,会转到403.jsp -->  
    11         <intercept-url pattern="/login" filters="none" />  
    12         <form-login login-page="/login"  
    13              authentication-failure-url="/login?error=true"  
    14              default-target-url="/index"/>
    15         <logout logout-success-url="/login" />
    16         <!-- 增加一个filter,这点与Acegi是不一样的,不能修改默认的filter了,这个filter位于FILTER_SECURITY_INTERCEPTOR之前 -->  
    17         <custom-filter before="FILTER_SECURITY_INTERCEPTOR" ref="myFilter" />  
    18     </http>  
    19     
    20     <!-- 认证管理器,实现用户认证的入口,主要实现UserDetailsService接口即可 -->  
    21     <authentication-manager alias="authenticationManager">  
    22         <authentication-provider  
    23             user-service-ref="myUserDetailService">  
    24             <!--    如果用户的密码采用加密的话,可以加点“盐”  
    25                  <password-encoder hash="md5" />  
    26             -->  
    27         </authentication-provider>  
    28     </authentication-manager>  
    29     
    30     
    31     <!-- 一个自定义的filter,必须包含authenticationManager,accessDecisionManager,securityMetadataSource三个属性,我们的所有控制将在这三个类中实现,解释详见具体配置 -->  
    32     <beans:bean id="myFilter" class="com.joyen.learning.security.MyFilterSecurityInterceptor">  
    33         <beans:property name="authenticationManager"  
    34              ref="authenticationManager" />  
    35         <beans:property name="accessDecisionManager"  
    36              ref="myAccessDecisionManagerBean" />  
    37         <beans:property name="securityMetadataSource"  
    38              ref="securityMetadataSource" />  
    39     </beans:bean>
    40     
    41     
    42     <beans:bean id="myUserDetailService"
    43          class="com.joyen.learning.security.MyUserDetailService">
    44          <beans:property name="dataSource" ref="dataSource"></beans:property>
    45         <beans:property name="usersByUsernameQuery" value="select username,password,email,enabled from user where username = ?"></beans:property>
    46         <beans:property name="authoritiesByUsernameQuery" value="SELECT u.username,r.name
    47                                                                     FROM user u,roleuser ru, role r
    48                                                                     WHERE u.id = ru.userid
    49                                                                     AND ru.roleid = r.id
    50                                                                     AND u.username = ?"></beans:property>
    51     </beans:bean>
    52   
    53     <!-- 访问决策器,决定某个用户具有的角色,是否有足够的权限去访问某个资源 -->  
    54     <beans:bean id="myAccessDecisionManagerBean"  
    55          class="com.joyen.learning.security.MyAccessDecisionManager">  
    56     </beans:bean>  
    57       
    58     <!-- 资源源数据定义,即定义某一资源可以被哪些角色访问 -->  
    59     <beans:bean id="securityMetadataSource"
    60          class="com.joyen.learning.security.MyInvocationSecurityMetadataSource">
    61         <beans:constructor-arg ref="dataSource"></beans:constructor-arg>
    62         <beans:constructor-arg type="java.lang.String" value="select rce.url, r.name from role r inner join roleresource rrce on r.id = rrce.roleid inner join resource rce on rrce.resourceid = rce.id"></beans:constructor-arg>
    63     </beans:bean>
    64 </beans:beans>
    spring-security.xml
  • 相关阅读:
    手把手教你用nodejs+SQL Server2012做增删改查
    js实现匀速运动及透明度动画
    SqlServer用sql对表名、字段做修改
    nodejs 使用fs实现多级联动
    关于此实现不是 Windows 平台 FIPS 验证的加密算法的一部分。
    访问快科技(驱动之家)某个新闻会自动跳转到web.techtoutiao.win
    在windows server上配置java jdk后,可能要些时间生效。
    .net webapi 收不到json 实体类参数,返回的json中带有k__BackingField
    空调 水槽 堵 用吹或吸都可以
    .net 4.0 程序遇到 停止工作 appcrash ,kernelbase.dll 等提示
  • 原文地址:https://www.cnblogs.com/mingluosunshan/p/5205901.html
Copyright © 2011-2022 走看看