Spring Security 3.1

原文地址 http://blog.csdn.net/u012367513/article/details/38866465
spring security 是现在比较流行的安全框架了,可以很容易的集成到项目中实现认证与授权的管理。本文基于spring security 3.1.3版本,主要参考了
L-二当家的的分享
LocalFilterSecurityInterceptor.java 登陆后,每次访问资源都会被这个拦截器拦截,会执行doFilter这个方法
package security;

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 LocalFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {

    //配置文件注入
    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 FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
        return this.securityMetadataSource;
    }

    public Class getSecureObjectClass() {
        return FilterInvocation.class;
    }

    public void invoke(FilterInvocation fi) throws IOException, ServletException {
        //fi里面有一个被拦截的url
        //里面调用LocalInvocationSecurityMetadataSource的getAttributes(Object object)这个方法获取fi对应的所有权限
        //再调用LocalAccessDecisionManager的decide方法来校验用户的权限是否足够
        InterceptorStatusToken token = super.beforeInvocation(fi);
        try {
            //执行下一个拦截器
            fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
        } finally {
            super.afterInvocation(token, null);
        }
    }

    public SecurityMetadataSource obtainSecurityMetadataSource() {
        return this.securityMetadataSource;
    }

    public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource newSource) {
        this.securityMetadataSource = newSource;
    }

    public void destroy() {

    }

    public void init(FilterConfig arg0) throws ServletException {

    }

}
LocalInvocationSecurityMetadataSource 这个用来加载资源与权限的全部对应关系的,并提供一个通过资源获取所有权限的方法
package security;

import java.util.*;

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 util.AntUrlPathMatcher;
import util.UrlMatcher;

public class LocalInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
    private UrlMatcher urlMatcher = new AntUrlPathMatcher();
    private static Map> resourceMap = null;

    //tomcat启动时实例化一次  
    public LocalInvocationSecurityMetadataSource() {
        loadResourceDefine();
    }
    //tomcat开启时加载一次,加载所有url和权限(或角色)的对应关系  
    private void loadResourceDefine() {
        resourceMap = new HashMap>();
        Collection atts = new ArrayList();
        ConfigAttribute ca = new SecurityConfig("ROLE_USER");
        atts.add(ca);
        resourceMap.put("/index.jsp", atts);
        Collection attsno =new ArrayList();
        ConfigAttribute cano = new SecurityConfig("ROLE_NO");
        attsno.add(cano);
        resourceMap.put("/other.jsp", attsno);

        Collection attsadmin =new ArrayList();
        ConfigAttribute canoadmin = new SecurityConfig("ROLE_ADMIN");
        attsadmin.add(canoadmin);
        resourceMap.put("/admin.jsp", attsadmin);
    }

    //参数是要访问的url,返回这个url对于的所有权限(或角色)  
    public Collection getAttributes(Object object) throws IllegalArgumentException {
        Collection configAttributes = new ArrayList();
        // 将参数转为url      
        String url = ((FilterInvocation)object).getRequestUrl();
        Iteratorite = resourceMap.keySet().iterator();
        while (ite.hasNext()) {
            String resURL = ite.next();
            if (urlMatcher.pathMatchesUrl(resURL, url)) {
                configAttributes.addAll(resourceMap.get(resURL));
            }
        }
        return configAttributes.isEmpty() ? null : configAttributes;
    }
    public boolean supports(Classclazz) {
        return true;
    }
    public Collection getAllConfigAttributes() {
        return null;
    }
}
LocalUserDetailService.java 提供通过用户名获取用户所有(包含权限)信息的接口
package security;

import org.springframework.dao.DataAccessException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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 java.util.ArrayList;
import java.util.Collection;

public class LocalUserDetailService implements UserDetailsService {

    //登陆验证时,通过username获取用户的所有权限信息,
    //并返回User放到spring的全局缓存SecurityContextHolder中,以供授权器使用
    public UserDetails loadUserByUsername(String username)
            throws UsernameNotFoundException, DataAccessException {
        Collection auths = new ArrayList();

        SimpleGrantedAuthority auth1=new SimpleGrantedAuthority("ROLE_ADMIN");
        SimpleGrantedAuthority auth2=new SimpleGrantedAuthority("ROLE_USER");
        SimpleGrantedAuthority auth3=new SimpleGrantedAuthority("ROLE_NO");
        //用户名是admin是天啊及所有权限
        if(username.equals("admin")){
            auths.add(auth1);
            auths.add(auth2);
            auths.add(auth3);
        }else {
            //其他情况去掉admin权限
            auths.add(auth2);
            auths.add(auth3);
        }
        //这里写死密码为admin,正常情况应该从数据库中查询
        User user = new User(username, "admin", true, true, true, true, auths);
        return user;
    }
}
LocalAccessDecisionManager.java 判断用户是否具有访问资源的权限
package security;

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.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;

public class LocalAccessDecisionManager implements AccessDecisionManager {

    //检查用户是否够权限访问资源  
    //参数authentication是从spring的全局缓存SecurityContextHolder中拿到的,里面是用户的权限信息  
    //参数object是url  
    //参数configAttributes所需的权限  
    public void decide(Authentication authentication, Object object,
                       Collection configAttributes)
            throws AccessDeniedException, InsufficientAuthenticationException {
        if (configAttributes == null) {
            return;
        }

        Iterator ite = configAttributes.iterator();
        while (ite.hasNext()) {
            ConfigAttribute ca = ite.next();
            String needRole = ca.getAttribute();
            for (GrantedAuthority ga : authentication.getAuthorities()) {
                if (needRole.equals(ga.getAuthority())) {
                    return;
                }
            }
        }
        //注意:执行这里,后台是会抛异常的,但是界面会跳转到所配的access-denied-page页面  
        throw new AccessDeniedException("no right");
    }

    public boolean supports(ConfigAttribute attribute) {
        return true;
    }

    public boolean supports(Class clazz) {
        return true;
    }
}
AntUrlPathMatcher.java 匹配url工具类
package util;

import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

public class AntUrlPathMatcher implements UrlMatcher {
    private boolean requiresLowerCaseUrl;
    private PathMatcher pathMatcher;

    public AntUrlPathMatcher()   {
        this(true);

    }

    public AntUrlPathMatcher(boolean requiresLowerCaseUrl)
    {
        this.requiresLowerCaseUrl = true;
        this.pathMatcher = new AntPathMatcher();
        this.requiresLowerCaseUrl = requiresLowerCaseUrl;
    }

    public Object compile(String path) {
        if (this.requiresLowerCaseUrl) {
            return path.toLowerCase();
        }
        return path;
    }

    public void setRequiresLowerCaseUrl(boolean requiresLowerCaseUrl){

        this.requiresLowerCaseUrl = requiresLowerCaseUrl;
    }

    public boolean pathMatchesUrl(Object path, String url) {
        if (("/**".equals(path)) || ("**".equals(path))) {
            return true;
        }

        return this.pathMatcher.match((String)path, url);
    }

    public String getUniversalMatchPattern() {
        return"/**";
    }

    public boolean requiresLowerCaseUrl() {
        return this.requiresLowerCaseUrl;
    }

    public String toString() {
        return super.getClass().getName() + "[requiresLowerCase='"
                + this.requiresLowerCaseUrl + "']";
    }
}
UrlMatcher.java 工具接口
package util;

public interface UrlMatcher{
    Object compile(String paramString);

    boolean pathMatchesUrl(Object paramObject, String paramString);

    String getUniversalMatchPattern();

    boolean requiresLowerCaseUrl();
}
securityConfig.xml spring-security 配置文件



    
    
    
        
        
        
        
         
        
            
        
        
        
    
    
    
        
        
        
    
    
    
        
            
        
    
    
    
    
    
    
    
    

web.xml


  
  
    contextConfigLocation
     classpath:securityConfig.xml
  
  
  
    springSecurityFilterChain
    org.springframework.web.filter.DelegatingFilterProxy
  
  
    springSecurityFilterChain
    /*
  
  
  
    org.springframework.web.context.ContextLoaderListener
  
  
  
    index.jsp
  
accessDenied.jsp 权限不足页面
<%@page pageEncoding="utf-8"%>



    My JSP 'accessDenied.jsp' starting page


accessDenied!!!

admin.jsp 管理员页面
<%@page pageEncoding="utf-8"%>



    My JSP 'admin.jsp' starting page


欢迎来到管理员页面.

index.jsp 主页
<%@page pageEncoding="UTF-8"%>



    My JSP 'index.jsp' starting page



这是首页

欢迎 进入admin页面 进入其它页面
login.jsp
<%@page pageEncoding="UTF-8"%>



    登录


用户:
密码:
other.jsp
<%@ page pageEncoding="UTF-8"%>



    My JSP 'other.jsp' starting page
    
    
    
    
    


这里是Other页面

pom 依赖

    3.1.3.RELEASE
    4.3.10.RELEASE
    3.0-alpha-1
  
  
    
      org.springframework
      spring-aop
      ${spring.version}
    
    
      org.springframework
      spring-core
      ${spring.version}
    
    
      org.springframework
      spring-context
      ${spring.version}
    
    
      org.springframework
      spring-tx
      ${spring.version}
    
    
      org.springframework
      spring-web
      ${spring.version}
    
    
      org.springframework.security
      spring-security-config
      ${spring-security.version}
    
    
      org.springframework.security
      spring-security-taglibs
      ${spring-security.version}
    
    
      org.springframework.security
      spring-security-web
      ${spring-security.version}
    
    
      javax.servlet
      servlet-api
      ${servlet-api.version}
      provided
    
  











你可能感兴趣的:(积累分享)