spring security 3 中使用自定义数据库来设置权限

参考文档: http://wenku.baidu.com/view/4ec7e324ccbff121dd368364.html

 

在spring security3中使用自己定义的数据结构来实现权限设置。

 

  1. 数据库
    • 用户表
    • 角色表
    • action表,即资源表
    • 角色-用户关联表
    • actiion-角色关联表
  2. 配置过程
    • web.xml中加入过滤器
      <!-- 配置spiring security --> <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> <!-- 配置spiring security结束 -->  
    • 在applicationContext.xml中import spring security部分的配置
      <import resource="security3.0_JPA.xml"/> 
    • 配置import resource="security3.0_JPA.xml
      <?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-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd"> <http auto-config="true" access-denied-page="/jsp/accessDenied.jsp"> <intercept-url pattern="/css/**" filters="none" /> <intercept-url pattern="/images/**" filters="none" /> <intercept-url pattern="/js/**" filters="none" /> <!-- 增加一个filter,这点与Acegi是不一样的,不能修改默认的filter了, 这个filter位于FILTER_SECURITY_INTERCEPTOR之前 --> <custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR" /> </http> <!-- 一个自定义的filter,必须包含authenticationManager,accessDecisionManager,securityMetadataSource三个属性, 我们的所有控制将在这三个类中实现,解释详见具体配置 --> <beans:bean id="myFilter" class="com.softvan.spring.security.FilterSecurityInterceptor"> <beans:property name="authenticationManager" ref="MyAuthenticationManager" /> <!-- 访问决策器,决定某个用户具有的角色,是否有足够的权限去访问某个资源 --> <beans:property name="accessDecisionManager" ref="AccessDecisionManager" /> <beans:property name="securityMetadataSource" ref="MySecurityMetadataSource" /> </beans:bean> <!-- 资源源数据定义,将所有的资源和权限对应关系建立起来,即定义某一资源可以被哪些角色访问 --> <beans:bean id="MySecurityMetadataSource" init-method="loadResourceDefine" class="com.softvan.spring.security.InvocationSecurityMetadataSourceService"> <beans:property name="roleService" ref="RoleService" /> <beans:property name="actionService" ref="ActionService" /> </beans:bean> <!-- 验证配置 , 认证管理器,实现用户认证的入口,主要实现UserDetailsService接口即可 --> <authentication-manager alias="MyAuthenticationManager"> <authentication-provider user-service-ref="UserDetailService"> <!-- <s:password-encoder hash="sha" /> --> </authentication-provider> </authentication-manager> </beans:beans> 
  3. 相关java代码
    • AccessDecisionManager.java
      /** * */ package com.softvan.spring.security; import org.apache.log4j.Logger; /** * @author 徐泽宇(roamer) * * 2010-7-4 */ import java.util.Collection; import java.util.Iterator; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.SecurityConfig; import org.springframework.security.authentication.InsufficientAuthenticationException; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.stereotype.Service; @Service("AccessDecisionManager") public class AccessDecisionManager implements org.springframework.security.access.AccessDecisionManager { /** * Logger for this class */ private static final Logger logger = Logger.getLogger(AccessDecisionManager.class); // In this method, need to compare authentication with configAttributes. // 1, A object is a URL, a filter was find permission configuration by this // URL, and pass to here. // 2, Check authentication has attribute in permission configuration // (configAttributes) // 3, If not match corresponding authentication, throw a // AccessDeniedException. public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException { if (logger.isDebugEnabled()) { logger.debug("decide(Authentication, Object, Collection<ConfigAttribute>) - start"); //$NON-NLS-1$ } if (configAttributes == null) { if (logger.isDebugEnabled()) { logger.debug("decide(Authentication, Object, Collection<ConfigAttribute>) - end"); //$NON-NLS-1$ } return; } if (logger.isDebugEnabled()){ logger.debug("正在访问的url是:"+object.toString()); } Iterator<ConfigAttribute> ite = configAttributes.iterator(); while (ite.hasNext()) { ConfigAttribute ca = ite.next(); logger.debug("needRole is:"+ca.getAttribute()); String needRole = ((SecurityConfig) ca).getAttribute(); for (GrantedAuthority ga : authentication.getAuthorities()) { logger.debug("/t授权信息是:"+ga.getAuthority()); if (needRole.equals(ga.getAuthority())) { // ga is user's role. if (logger.isDebugEnabled()) { logger.debug("判断到,needRole 是"+needRole+",用户的角色是:"+ga.getAuthority()+",授权数据相匹配"); logger.debug("decide(Authentication, Object, Collection<ConfigAttribute>) - end"); //$NON-NLS-1$ } return; } } } throw new AccessDeniedException("没有权限"); } public boolean supports(ConfigAttribute attribute) { // TODO Auto-generated method stub return true; } public boolean supports(Class<?> clazz) { return true; } } 
    • FilterSecurityInterceptor.java
      /** * */ package com.softvan.spring.security; import org.apache.log4j.Logger; /** * @author 徐泽宇(roamer) * * 2010-7-4 */ import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import org.springframework.security.access.SecurityMetadataSource; import org.springframework.security.access.intercept.AbstractSecurityInterceptor; import org.springframework.security.access.intercept.InterceptorStatusToken; import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; public class FilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter { /** * Logger for this class */ private static final Logger logger = Logger.getLogger(FilterSecurityInterceptor.class); private FilterInvocationSecurityMetadataSource securityMetadataSource; public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (logger.isDebugEnabled()) { logger.debug("doFilter(ServletRequest, ServletResponse, FilterChain) - start"); //$NON-NLS-1$ } FilterInvocation fi = new FilterInvocation(request, response, chain); invoke(fi); if (logger.isDebugEnabled()) { logger.debug("doFilter(ServletRequest, ServletResponse, FilterChain) - end"); //$NON-NLS-1$ } } public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() { return this.securityMetadataSource; } public Class<? extends Object> getSecureObjectClass() { return FilterInvocation.class; } public void invoke(FilterInvocation fi) throws IOException, ServletException { InterceptorStatusToken token = super.beforeInvocation(fi); try { fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); } finally { super.afterInvocation(token, null); } } @Override public SecurityMetadataSource obtainSecurityMetadataSource() { return this.securityMetadataSource; } public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource securityMetadataSource) { this.securityMetadataSource = securityMetadataSource; } public void destroy() { // TODO Auto-generated method stub } public void init(FilterConfig filterconfig) throws ServletException { // TODO Auto-generated method stub } } 
    • InvocationSecurityMetadataSourceService.java
      /** * */ package com.softvan.spring.security; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.SecurityConfig; import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; import org.springframework.security.web.util.AntUrlPathMatcher; import org.springframework.security.web.util.UrlMatcher; import org.springframework.stereotype.Service; import com.alcor.acl.domain.TAction; import com.alcor.acl.domain.TRole; import com.alcor.acl.service.ActionService; import com.alcor.acl.service.RoleService; /* * * 最核心的地方,就是提供某个资源对应的权限定义,即getAttributes方法返回的结果。 * 注意,我例子中使用的是AntUrlPathMatcher这个path matcher来检查URL是否与资源定义匹配, * 事实上你还要用正则的方式来匹配,或者自己实现一个matcher。 * * 此类在初始化时,应该取到所有资源及其对应角色的定义 * * 说明:对于方法的spring注入,只能在方法和成员变量里注入, * 如果一个类要进行实例化的时候,不能注入对象和操作对象, * 所以在构造函数里不能进行操作注入的数据。 */ @Service("InvocationSecurityMetadataSourceService") public class InvocationSecurityMetadataSourceService implements FilterInvocationSecurityMetadataSource { /** * Logger for this class */ private static final Logger logger = Logger.getLogger(InvocationSecurityMetadataSourceService.class); private RoleService roleService ; private ActionService actionService; private UrlMatcher urlMatcher = new AntUrlPathMatcher(); private static Map<String, Collection<ConfigAttribute>> resourceMap = null; public void loadResourceDefine()throws Exception { this.resourceMap = new HashMap<String, Collection<ConfigAttribute>>(); //通过数据库中的信息设置,resouce和role for (TRole item:this.roleService.getAllRoles()){ Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>(); ConfigAttribute ca = new SecurityConfig(item.getRoleName()); atts.add(ca); List<TAction> tActionList = actionService.findByRoleID(item.getRoleId()); //把资源放入到spring security的resouceMap中 for(TAction tAction:tActionList){ logger.debug("获得角色:["+item.getRoleName()+"]拥有的acton有:"+tAction.getActionUrl()); this.resourceMap.put(tAction.getActionUrl(), atts); } } /*//通过硬编码设置,resouce和role resourceMap = new HashMap<String, Collection<ConfigAttribute>>(); Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>(); ConfigAttribute ca = new SecurityConfig("admin"); atts.add(ca); resourceMap.put("/jsp/admin.jsp", atts); resourceMap.put("/swf/zara.html", atts);*/ } // According to a URL, Find out permission configuration of this URL. public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException { if (logger.isDebugEnabled()) { logger.debug("getAttributes(Object) - start"); //$NON-NLS-1$ } // guess object is a URL. String url = ((FilterInvocation) object).getRequestUrl(); Iterator<String> ite = resourceMap.keySet().iterator(); while (ite.hasNext()) { String resURL = ite.next(); if (urlMatcher.pathMatchesUrl(url, resURL)) { Collection<ConfigAttribute> returnCollection = resourceMap.get(resURL); if (logger.isDebugEnabled()) { logger.debug("getAttributes(Object) - end"); //$NON-NLS-1$ } return returnCollection; } } if (logger.isDebugEnabled()) { logger.debug("getAttributes(Object) - end"); //$NON-NLS-1$ } return null; } public boolean supports(Class<?> clazz) { return true; } public Collection<ConfigAttribute> getAllConfigAttributes() { return null; } public RoleService getRoleService() { return roleService; } public void setRoleService(RoleService roleService) { this.roleService = roleService; } public ActionService getActionService() { return actionService; } public void setActionService(ActionService actionService) { this.actionService = actionService; } } 
    • UserDetailService.java
      /** * */ package com.softvan.spring.security; import java.util.ArrayList; import java.util.Collection; import java.util.Set; import javax.inject.Inject; import org.apache.log4j.Logger; import org.springframework.dao.DataAccessException; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.GrantedAuthorityImpl; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import com.alcor.acl.domain.TRole; import com.alcor.acl.domain.TUser; @Service("UserDetailService") public class UserDetailService implements UserDetailsService { /** * Logger for this class */ private static final Logger logger = Logger.getLogger(UserDetailService.class); @Inject com.alcor.acl.component.User user ; public UserDetails loadUserByUsername(String username)throws UsernameNotFoundException, DataAccessException { if (logger.isDebugEnabled()) { logger.debug("loadUserByUsername(String) - start"); //$NON-NLS-1$ } Collection<GrantedAuthority> auths=new ArrayList<GrantedAuthority>(); String password=null; //取得用户的密码 TUser tUser = user.getUserByName(username); if (tUser ==null){ String message = "用户"+username+"不存在"; logger.error(message); throw new UsernameNotFoundException(message); } password=user.getUserByName(username).getPassword(); //获得用户的角色 Set<TRole> tRoles =tUser.getTRoles(); for(TRole item : tRoles){ GrantedAuthorityImpl grantedAuthorityImpl = new GrantedAuthorityImpl(item.getRoleName()); if (logger.isDebugEnabled()){ logger.debug("用户:["+tUser.getName()+"]拥有角色:["+item.getRoleName()+"],即spring security中的access"); } auths.add(grantedAuthorityImpl); } User user = new User(username,password, true, true, true, true, auths); if (logger.isDebugEnabled()) { logger.debug("loadUserByUsername(String) - end"); //$NON-NLS-1$ } return user; } }

你可能感兴趣的:(spring,数据库,object,filter,Security,Authentication)