spring security JDBC 数据库实现,5个表, 例子下载

在前面用 srpng security  hibernate, mysql 做了一个简单的例子,仅仅用户和和角色,用户与角色的关系用数据库来保存,而对资源管理仍然用XML 配置方式来实现,对于某些特殊要求的项目来说,仍然没办法满足要求,于是就有了5张表的 Spring security  的扩展实现。在网上参考过别人很多文章以及博客,但总是没怎么成功过,关键是人家也不提供整个代码下载,所以很多细节不知道。好不容易试验出来,特地放出代码在本文最后下载。

创建  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.获取请求资源的权限
        // 执行Collection<ConfigAttribute> attributes =
        // 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,Collection<ConfigAttribute> configAttributes)
    {
        if (configAttributes == null) {
            return;
        }
        //所请求的资源拥有的权限(一个资源对多个权限)
        Iterator<ConfigAttribute> 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<ConfigAttribute>,资源权限对应Map
    private static Map<String, Collection<ConfigAttribute>> resourceMap = null;

    public MyInvocationSecurityMetadataSourceService(ResourcesDao resourcesDao) {
        this.resourcesDao = resourcesDao;
        System.out.println("加载MyInvocationSecurityMetadataSourceService..."
                + resourcesDao);
        loadResourceDefine();
    }

    // 加载所有资源与权限的关系
    private void loadResourceDefine() {
        if (resourceMap == null) {
            resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
            List<SysResource> resources = resourcesDao.findAll();
            // 加载资源对应的权限
            for (SysResource resource : resources) {
                Collection<ConfigAttribute> auths = resourcesDao
                        .loadRoleByResource(resource.getResource());
                System.out.println("权限=" + auths);
                resourceMap.put(resource.getResource(), auths);
            }
        }
    }

    // 加载所有资源与权限的关系
    public Collection<ConfigAttribute> 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<String> 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<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

}


运行程序,这样就能实现对数据库中配置的资源的拦截,有权限的就能访问,否则403错误. 整个代码下载:
下载文件 spring security database source code free download

参考的文章如下,原来来自百度文库:下载文件 spring security document


除非申明,文章均为一号门原创,转载请注明本文地址,谢谢!
[本日志由 轻舞肥羊 于 2013-12-26 11:24 PM 编辑]
文章来自: 本站原创
引用通告: 查看所有引用 | 我要引用此文章
Tags: spring security
相关日志:
评论: 0 | 引用: 0 | 查看次数: -
发表评论
昵 称:
密 码: 游客发言不需要密码.
内 容:
验证码: 验证码
选 项:
虽然发表评论不用注册,但是为了保护您的发言权,建议您注册帐号.