Spring Security 2 配置精讲 完整代码

本文介绍了一个基于Spring Security的权限管理系统实现方案,包括资源、角色及用户的定义,以及如何通过Spring Security进行权限验证和配置。

Resource

 

 

@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Resource {

 @Id
    @GeneratedValue
 private Integer id;
 
 private String type;
 
 private String value;
 
 @ManyToMany(mappedBy = "resources", targetEntity = Role.class, fetch = FetchType.EAGER)
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
 private Set<Role> roles;
 
 /**
  * The default constructor
  */
 public Resource() {
  
 }
 
    /**
     * Get role authorities as string
     *
     * @return
     */
    @Transient
 public String getRoleAuthorities() {
     List<String> roleAuthorities = new ArrayList<String>();
     for(Role role : roles) {
      roleAuthorities.add(role.getName());
     }
        return StringUtils.join(roleAuthorities, ",");
    }

 /**
  * @return the id
  */
 public Integer getId() {
  return id;
 }

 /**
  * @return the type
  */
 public String getType() {
  return type;
 }

 /**
  * @return the value
  */
 public String getValue() {
  return value;
 }

 /**
  * @return the roles
  */
 public Set<Role> getRoles() {
  return roles;
 }

 /**
  * @param id the id to set
  */
 public void setId(Integer id) {
  this.id = id;
 }

 /**
  * @param type the type to set
  */
 public void setType(String type) {
  this.type = type;
 }

 /**
  * @param value the value to set
  */
 public void setValue(String value) {
  this.value = value;
 }

 /**
  * @param roles the roles to set
  */
 public void setRoles(Set<Role> roles) {
  this.roles = roles;
 }

}


 

@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Role {
 
 @Id
 @GeneratedValue
 private Integer id;
 
 private String name;
 
 private String description;
 
 @ManyToMany(targetEntity = Resource.class, fetch = FetchType.EAGER)
    @JoinTable(name = "role_resource", joinColumns = @JoinColumn(name = "role_id"), inverseJoinColumns = @JoinColumn(name = "resource_id"))
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
 private Set<Resource> resources;
 
 /**
  * The default constructor
  */
 public Role() {
  
 }

 /**
  * @return the id
  */
 public Integer getId() {
  return id;
 }

 /**
  * @return the name
  */
 public String getName() {
  return name;
 }
 
 /**
  * @return the description
  */
 public String getDescription() {
  return description;
 }

 /**
  * @return the resources
  */
 public Set<Resource> getResources() {
  return resources;
 }

 /**
  * @param id the id to set
  */
 public void setId(Integer id) {
  this.id = id;
 }

 /**
  * @param name the name to set
  */
 public void setName(String name) {
  this.name = name;
 }
 
 /**
  * @param description the description to set
  */
 public void setDescription(String description) {
  this.description = description;
 }

 /**
  * @param resources the resources to set
  */
 public void setResources(Set<Resource> resources) {
  this.resources = resources;
 }

}

 

 


 

@Entity
@Proxy(lazy = false)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class User implements UserDetails {
 
 private static final long serialVersionUID = 8026813053768023527L;

    @Id
 @GeneratedValue
 private Integer id;
 
 private String name;
 
 private String password;
 
 private boolean disabled;
 
 @ManyToMany(targetEntity = Role.class, fetch = FetchType.EAGER)
    @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
 private Set<Role> roles;
 
 @Transient
 private Map<String, List<Resource>> roleResources;
 
 /**
  * The default constructor
  */
 public User() {
  
 }

 /* (non-Javadoc)
  * @see org.springframework.security.userdetails.UserDetails#getAuthorities()
  */
 public GrantedAuthority[] getAuthorities() {
  List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>(roles.size());
     for(Role role : roles) {
      grantedAuthorities.add(new GrantedAuthorityImpl(role.getName()));
     }
        return grantedAuthorities.toArray(new GrantedAuthority[roles.size()]);
 }
 
 /**
  * Returns the authorites string
  *
  * eg.
  *    downpour --- ROLE_ADMIN,ROLE_USER
  *    robbin --- ROLE_ADMIN
  *
  * @return
  */
 public String getAuthoritiesString() {
     List<String> authorities = new ArrayList<String>();
     for(GrantedAuthority authority : this.getAuthorities()) {
         authorities.add(authority.getAuthority());
     }
     return StringUtils.join(authorities, ",");
 }

 /* (non-Javadoc)
  * @see org.springframework.security.userdetails.UserDetails#getPassword()
  */
 public String getPassword() {
  return password;
 }

 /* (non-Javadoc)
  * @see org.springframework.security.userdetails.UserDetails#getUsername()
  */
 public String getUsername() {
  return name;
 }

 /* (non-Javadoc)
  * @see org.springframework.security.userdetails.UserDetails#isAccountNonExpired()
  */
 public boolean isAccountNonExpired() {
  return true;
 }

 /* (non-Javadoc)
  * @see org.springframework.security.userdetails.UserDetails#isAccountNonLocked()
  */
 public boolean isAccountNonLocked() {
  return true;
 }

 /* (non-Javadoc)
  * @see org.springframework.security.userdetails.UserDetails#isCredentialsNonExpired()
  */
 public boolean isCredentialsNonExpired() {
  return true;
 }

 /* (non-Javadoc)
  * @see org.springframework.security.userdetails.UserDetails#isEnabled()
  */
 public boolean isEnabled() {
  return !disabled;
 }

 /**
  * @return the id
  */
 public Integer getId() {
  return id;
 }

 /**
  * @return the name
  */
 public String getName() {
  return name;
 }

 /**
  * @return the disabled
  */
 public boolean isDisabled() {
  return disabled;
 }

 /**
  * @return the roles
  */
 public Set<Role> getRoles() {
  return roles;
 }

 /**
  * @return the roleResources
  */
 public Map<String, List<Resource>> getRoleResources() {
  // init roleResources for the first time
  if(this.roleResources == null) {
   
   this.roleResources = new HashMap<String, List<Resource>>();
   
   for(Role role : this.roles) {
    String roleName = role.getName();
    Set<Resource> resources = role.getResources();
    for(Resource resource : resources) {
     String key = roleName + "_" + resource.getType();
     if(!this.roleResources.containsKey(key)) {
      this.roleResources.put(key, new ArrayList<Resource>());
     }
     this.roleResources.get(key).add(resource);     
    }
   }
   
  }
  return this.roleResources;
 }

 /**
  * @param id the id to set
  */
 public void setId(Integer id) {
  this.id = id;
 }

 /**
  * @param name the name to set
  */
 public void setName(String name) {
  this.name = name;
 }

 /**
  * @param password the password to set
  */
 public void setPassword(String password) {
  this.password = password;
 }

 /**
  * @param disabled the disabled to set
  */
 public void setDisabled(boolean disabled) {
  this.disabled = disabled;
 }

 /**
  * @param roles the roles to set
  */
 public void setRoles(Set<Role> roles) {
  this.roles = roles;
 }
 
}


 

public class SecureResourceFilterInvocationDefinitionSource implements FilterInvocationDefinitionSource, InitializingBean {
   
    private UrlMatcher urlMatcher;

    private boolean useAntPath = true;
   
    private boolean lowercaseComparisons = true;
   
    /**
     * @param useAntPath the useAntPath to set
     */
    public void setUseAntPath(boolean useAntPath) {
        this.useAntPath = useAntPath;
    }
   
    /**
     * @param lowercaseComparisons
     */
    public void setLowercaseComparisons(boolean lowercaseComparisons) {
        this.lowercaseComparisons = lowercaseComparisons;
    }
   
    /* (non-Javadoc)
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
     */
    public void afterPropertiesSet() throws Exception {
       
        // default url matcher will be RegexUrlPathMatcher
        this.urlMatcher = new RegexUrlPathMatcher();
       
        if (useAntPath) {  // change the implementation if required
            this.urlMatcher = new AntUrlPathMatcher();
        }
       
        // Only change from the defaults if the attribute has been set
        if ("true".equals(lowercaseComparisons)) {
            if (!this.useAntPath) {
                ((RegexUrlPathMatcher) this.urlMatcher).setRequiresLowerCaseUrl(true);
            }
        } else if ("false".equals(lowercaseComparisons)) {
            if (this.useAntPath) {
                ((AntUrlPathMatcher) this.urlMatcher).setRequiresLowerCaseUrl(false);
            }
        }
       
    }
   
    /* (non-Javadoc)
     * @see org.springframework.security.intercept.ObjectDefinitionSource#getAttributes(java.lang.Object)
     */
    public ConfigAttributeDefinition getAttributes(Object filter) throws IllegalArgumentException {
       
        FilterInvocation filterInvocation = (FilterInvocation) filter;
        String requestURI = filterInvocation.getRequestUrl();
        Map<String, String> urlAuthorities = this.getUrlAuthorities(filterInvocation);
       
        String grantedAuthorities = null;
        for(Iterator<Map.Entry<String, String>> iter = urlAuthorities.entrySet().iterator(); iter.hasNext();) {
            Map.Entry<String, String> entry = iter.next();
            String url = entry.getKey();
           
            if(urlMatcher.pathMatchesUrl(url, requestURI)) {
                grantedAuthorities = entry.getValue();
                break;
            }
           
        }
       
        if(grantedAuthorities != null) {
            ConfigAttributeEditor configAttrEditor = new ConfigAttributeEditor();
            configAttrEditor.setAsText(grantedAuthorities);
            return (ConfigAttributeDefinition) configAttrEditor.getValue();
        }
       
        return null;
    }

    /* (non-Javadoc)
     * @see org.springframework.security.intercept.ObjectDefinitionSource#getConfigAttributeDefinitions()
     */
    @SuppressWarnings("unchecked")
 public Collection getConfigAttributeDefinitions() {
        return null;
    }

    /* (non-Javadoc)
     * @see org.springframework.security.intercept.ObjectDefinitionSource#supports(java.lang.Class)
     */
    @SuppressWarnings("unchecked")
 public boolean supports(Class clazz) {
        return true;
    }
   
    /**
     *
     * @param filterInvocation
     * @return
     */
    @SuppressWarnings("unchecked")
 private Map<String, String> getUrlAuthorities(FilterInvocation filterInvocation) {
        ServletContext servletContext = filterInvocation.getHttpRequest().getSession().getServletContext();
        return (Map<String, String>)servletContext.getAttribute("urlAuthorities");
    }

}

 

 


 

 

@Service("securityManager")
public class SecurityManagerSupport extends HibernateDaoSupport implements UserDetailsService, SecurityManager {
   
    /**
     * Init sessionFactory here because the annotation of Spring 2.5 can not support override inject
     * 
     * @param sessionFactory
     */
    @Autowired
    public void init(SessionFactory sessionFactory) {
        super.setSessionFactory(sessionFactory);
    }
   
    /* (non-Javadoc)
     * @see org.springframework.security.userdetails.UserDetailsService#loadUserByUsername(java.lang.String)
     */
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException, DataAccessException {
        List<User> users = getHibernateTemplate().find("FROM User user WHERE user.name = ? AND user.disabled = false", userName);
        if(users.isEmpty()) {
            throw new UsernameNotFoundException("User " + userName + " has no GrantedAuthority");
        }
        return users.get(0);
    }
   
    /* (non-Javadoc)
     * @see com.javaeye.sample.security.SecurityManager#loadUrlAuthorities()
     */
    public Map<String, String> loadUrlAuthorities() {
        Map<String, String> urlAuthorities = new HashMap<String, String>();
        List<Resource> urlResources = getHibernateTemplate().find("FROM Resource resource WHERE resource.type = ?", "URL");
        for(Resource resource : urlResources) {
            urlAuthorities.put(resource.getValue(), resource.getRoleAuthorities());
        }
        return urlAuthorities;
    }

   
}

 


 

 

public class SecurityUserHolder {

 /**
  * Returns the current user
  *
  * @return
  */
 public static User getCurrentUser() {
  return (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
 }

}

 


 

 

public interface SecurityManager {
    
    public Map<String, String> loadUrlAuthorities();
       
}

 


 

public class ServletContextLoaderListener implements ServletContextListener {

    /* (non-Javadoc)
     * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent)
     */
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        ServletContext servletContext = servletContextEvent.getServletContext();
        SecurityManager securityManager = this.getSecurityManager(servletContext);
       
        Map<String, String> urlAuthorities = securityManager.loadUrlAuthorities();
        servletContext.setAttribute("urlAuthorities", urlAuthorities);
    }

   
    /* (non-Javadoc)
     * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)
     */
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        servletContextEvent.getServletContext().removeAttribute("urlAuthorities");
    }

    /**
     * Get SecurityManager from ApplicationContext
     *
     * @param servletContext
     * @return
     */
    protected SecurityManager getSecurityManager(ServletContext servletContext) {
       return (SecurityManager) WebApplicationContextUtils.getWebApplicationContext(servletContext).getBean("securityManager");
    }

}

 


 

public class Index extends HttpServlet {

    private static final long serialVersionUID = -2695430823076562265L;

    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       
        User user = SecurityUserHolder.getCurrentUser();
        request.setAttribute("currentUser", user);
       
        RequestDispatcher dispatcher = request.getRequestDispatcher("/index.jsp"); 
        dispatcher.forward(request, response);
    }
   
    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}


 

 

 

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="Yoda" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
 <display-name>Yoda</display-name>

    <!-- Spring ApplicationContext Definition -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/classes/context/applicationContext-*.xml</param-value>
    </context-param>
   
    <!-- Spring security Filter -->
    <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>

 <servlet>
  <servlet-name>index</servlet-name>
  <servlet-class>com.javaeye.sample.web.servlet.Index</servlet-class>
 </servlet>
 
 <servlet-mapping>
  <servlet-name>index</servlet-name>
  <url-pattern>/index</url-pattern>
 </servlet-mapping>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
   
    <listener>
        <listener-class>com.javaeye.sample.web.loader.ServletContextLoaderListener</listener-class>
    </listener>
   
   
            
</web-app>

 

 


 

 

<?xml version="1.0" encoding="UTF-8"?>

<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.4.xsd">
 
 <beans:bean id="loggerListener" class="org.springframework.security.event.authentication.LoggerListener" />
 
 <http access-denied-page="/403.jsp" >
  <intercept-url pattern="/static/**" filters="none" />
  <intercept-url pattern="/template/**" filters="none" />
  <intercept-url pattern="/" filters="none" />
  <intercept-url pattern="/login.jsp" filters="none" />
     <form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?error=true" default-target-url="/index" />
     <logout logout-success-url="/login.jsp"/>
     <http-basic />
 </http>

 <authentication-manager alias="authenticationManager"/>
 
 <authentication-provider user-service-ref="securityManager">
  <password-encoder hash="md5"/>
 </authentication-provider>
 
 <beans:bean id="accessDecisionManager" class="org.springframework.security.vote.AffirmativeBased">
     <beans:property name="allowIfAllAbstainDecisions" value="false"/>
     <beans:property name="decisionVoters">
         <beans:list>
             <beans:bean class="org.springframework.security.vote.RoleVoter"/>
             <beans:bean class="org.springframework.security.vote.AuthenticatedVoter"/>
         </beans:list>
     </beans:property>
 </beans:bean>
 
 <beans:bean id="resourceSecurityInterceptor" class="org.springframework.security.intercept.web.FilterSecurityInterceptor">
  <beans:property name="authenticationManager" ref="authenticationManager"/>
     <beans:property name="accessDecisionManager" ref="accessDecisionManager"/>
     <beans:property name="objectDefinitionSource" ref="secureResourceFilterInvocationDefinitionSource" />
     <beans:property name="observeOncePerRequest" value="false" />
     <custom-filter after="LAST" />
 </beans:bean>
 
 <beans:bean id="secureResourceFilterInvocationDefinitionSource" class="com.javaeye.sample.security.interceptor.SecureResourceFilterInvocationDefinitionSource" />
 
</beans:beans>

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值