spring security JDBC 数据库实现,5个表, 例子下载
By:Roy.LiuLast updated:2013-12-26
在前面用 srpng security hibernate, mysql 做了一个简单的例子,仅仅用户和和角色,用户与角色的关系用数据库来保存,而对资源管理仍然用XML 配置方式来实现,对于某些特殊要求的项目来说,仍然没办法满足要求,于是就有了5张表的 Spring security 的扩展实现。在网上参考过别人很多文章以及博客,但总是没怎么成功过,关键是人家也不提供整个代码下载,所以很多细节不知道。好不容易试验出来,特地放出代码在本文最后下载。
创建 spring security 所要用到的表, 并初始化数据
spring security data schema free downlaod
重点在与对资源的拦截
由于提供了代码下载,所以有些地方就不必详细介绍了,而且在前面的文章中,也有讲到,所以重点是怎么拦截资源的实现.
另外还需要实现 FilterInvocationSecurityMetadataSource 接口 以及 AccessDecisionManager 来判断用户是否有访问资源的权限。在代码中注意如下的两个类 :
运行程序,这样就能实现对数据库中配置的资源的拦截,有权限的就能访问,否则403错误. 整个代码下载:
spring security database source code free download
参考的文章如下,原来来自百度文库:spring security document
创建 spring security 所要用到的表, 并初始化数据
spring security data schema free downlaod
重点在与对资源的拦截
由于提供了代码下载,所以有些地方就不必详细介绍了,而且在前面的文章中,也有讲到,所以重点是怎么拦截资源的实现.
package com.yihaomen.common.intercept; 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.beans.factory.annotation.Autowired; 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 MyFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter { // 与spring-security.xml里的myFilter的属性securityMetadataSource对应, // 其他的两个组件,已经在AbstractSecurityInterceptor定义 @Autowired private FilterInvocationSecurityMetadataSource securityMetadataSource; public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { FilterInvocation fi = new FilterInvocation(request, response, chain); invoke(fi); } public Class extends Object> getSecureObjectClass() { return FilterInvocation.class; } public void invoke(FilterInvocation fi) throws IOException, ServletException { // object为FilterInvocation对象 // super.beforeInvocation(fi);源码 // 1.获取请求资源的权限 // 执行Collectionattributes = // SecurityMetadataSource.getAttributes(object); // 2.是否拥有权限 // this.accessDecisionManager.decide(authenticated, object, attributes); 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() { } public void init(FilterConfig filterconfig) throws ServletException { } }
另外还需要实现 FilterInvocationSecurityMetadataSource 接口 以及 AccessDecisionManager 来判断用户是否有访问资源的权限。在代码中注意如下的两个类 :
package com.yihaomen.comm.service; import java.util.Collection; import java.util.Iterator; import org.springframework.security.access.AccessDecisionManager; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.SecurityConfig; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; public class MyAccessDecisionManager implements AccessDecisionManager { public void decide(Authentication authentication, Object object,CollectionconfigAttributes) { if (configAttributes == null) { return; } //所请求的资源拥有的权限(一个资源对多个权限) Iterator ite = configAttributes.iterator(); while (ite.hasNext()) { ConfigAttribute ca = ite.next(); //访问所请求资源所需要的权限 String needRole = ((SecurityConfig) ca).getAttribute(); System.out.println("needRole is " + needRole); // ga 为用户所被赋予的权限。 needRole 为访问相应的资源应该具有的权限。 for (GrantedAuthority ga : authentication.getAuthorities()) { if (needRole.trim().equals(ga.getAuthority().trim())) { System.out.println("有相关的权限"); return; } } throw new AccessDeniedException("can not access this page"); } } public boolean supports(ConfigAttribute arg0) { return true; } public boolean supports(Class> arg0) { return true; } }
package com.yihaomen.comm.service; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; import com.yihaomen.common.dao.ResourcesDao; import com.yihaomen.common.domain.SysResource; public class MyInvocationSecurityMetadataSourceService implements FilterInvocationSecurityMetadataSource { @Autowired private ResourcesDao resourcesDao; // resourceMap及为key-url,value-Collection,资源权限对应Map private static Map > resourceMap = null; public MyInvocationSecurityMetadataSourceService(ResourcesDao resourcesDao) { this.resourcesDao = resourcesDao; System.out.println("加载MyInvocationSecurityMetadataSourceService..." + resourcesDao); loadResourceDefine(); } // 加载所有资源与权限的关系 private void loadResourceDefine() { if (resourceMap == null) { resourceMap = new HashMap >(); List resources = resourcesDao.findAll(); // 加载资源对应的权限 for (SysResource resource : resources) { Collection auths = resourcesDao .loadRoleByResource(resource.getResource()); System.out.println("权限=" + auths); resourceMap.put(resource.getResource(), auths); } } } // 加载所有资源与权限的关系 public Collection getAttributes(Object object) throws IllegalArgumentException { // object是一个URL,被用户请求的url String requestUrl = ((FilterInvocation) object).getRequestUrl(); System.out.println("requestUrl is " + requestUrl); int firstQuestionMarkIndex = requestUrl.indexOf("?"); if (firstQuestionMarkIndex != -1) { requestUrl = requestUrl.substring(0, firstQuestionMarkIndex); } if (resourceMap == null) { loadResourceDefine(); } Iterator ite = resourceMap.keySet().iterator(); while (ite.hasNext()) { String resURL = ite.next(); if (resURL.equals(requestUrl)) { return resourceMap.get(resURL); } } return null; } public boolean supports(Class> arg0) { return true; } public Collection getAllConfigAttributes() { return null; } }
运行程序,这样就能实现对数据库中配置的资源的拦截,有权限的就能访问,否则403错误. 整个代码下载:
spring security database source code free download
参考的文章如下,原来来自百度文库:spring security document
From:一号门
Previous:写sql语句时应注意的事项
Next:自定义ehcache工具类实现缓存
COMMENTS