zoukankan      html  css  js  c++  java
  • spring security 3.2 配置详解(结合数据库)

    没事就来了解下spring security.网上找了很多资料。有过时的,也有不是很全面的。各种问题也算是让我碰了个遍。这样吧。我先把整个流程写下来,之后在各个易混点分析吧。

    1.建立几个必要的页面。

    login.jsp   index.jsp    user.jsp     admin.jsp    error.jsp 后面几个只是用来做跳转的,里面没什么要注意的,就贴出login里面的吧

    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>login</title>
    </head>
    <body>
        <form action="/mavenTest/j_spring_security_check" method="post">
            账户:<input type="text" name="j_username" id="username"/>
            密码:<input type="text" name="j_password" id="password"/>
            <input type="submit" value="登陆"/>
        </form>
    </body>
    </html>

    2.配置web.xml  没有用的就没有粘贴了

    <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>

    3.忘记吧pom.xml文件给出来了  版本为<org.springframework-version>3.2.3.RELEASE</org.springframework-version>

    <!-- spring security -->
              <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-core</artifactId>
                <version>${org.springframework-version}</version>
              </dependency>
    
              <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-web</artifactId>
                <version>${org.springframework-version}</version>
              </dependency>
    
              <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-config</artifactId>
                <version>${org.springframework-version}</version>
              </dependency>

    4.配置spring security .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.2.xsd
               http://www.springframework.org/schema/security
               http://www.springframework.org/schema/security/spring-security.xsd">
         
         <!-- 不需要进行安全认证的资源 -->
        <http pattern="/resources/**" security="none" />
        <http pattern="/login.jsp" security="none"/>
        
        <!-- 资源所需要的权限 -->
        <http auto-config='true'>
            <form-login login-page="/login.jsp" 
                default-target-url="/index.jsp"
                authentication-failure-url="/login.jsp?error=true" />
            <logout logout-success-url="/index.jsp"/>
            
            <!-- 尝试访问没有权限的页面时跳转的页面 -->
            <access-denied-handler error-page="/error-noauth.jsp"/>
            
            <custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR"/>
        </http>
        
        <!-- 自定义一个filter,必须包含authenticationManager,accessDecisionManager,
        securityMetadataSource三个属性 所有的功能都在这三个类中实现-->
        
        <beans:bean id="myFilter" class="com.demo.im.model.security.MyFilterSecurotyInterceptor">
            <beans:property name="authenticationManager" 
            ref="authenticationManager" />
            <beans:property name="accessDecisionManager" 
            ref ="myAccessDecisionManagerBean"/>
            <beans:property name="securityMetadataSource" 
            ref="securityMetadaSource"/>
        </beans:bean>
        
        <!-- 认证管理器,实现用户认证的入口,主要实现userdetailsservice -->
        <authentication-manager alias="authenticationManager">
            <authentication-provider
                user-service-ref="myUserDetailService">
            </authentication-provider>
        </authentication-manager>
        
        <beans:bean id="myUserDetailService"
            class="com.demo.im.model.security.DefaultUserDetailsService">
        </beans:bean>
        
        <!-- 访问决策,决定某个用户具有的角色,是否有足够的权限去访问某个资源 -->
        <beans:bean id="myAccessDecisionManagerBean"
            class="com.demo.im.model.security.MyAccessDecisionManager" />
        
        <beans:bean id="securityMetadaSource" 
            class="com.demo.im.model.security.MyInvocationSecurityMetadaSource"/>
        
    </beans:beans>

    5.MyFilterSecurotyInterceptor   自定义filter的代码如下。

    其中最核心的代码是  invoke() 方法中的  

    InterceptorStatusToken token = super.beforeInvocation(fi);
    这一句在dofilter之前进行权限验证,而具体的实现交给了accessDecisionManager,下面将继续讨论

    package com.demo.im.model.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 MyFilterSecurotyInterceptor extends AbstractSecurityInterceptor implements Filter {
    
        private FilterInvocationSecurityMetadataSource securityMetadataSource;
        
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response,
                FilterChain chain) throws IOException, ServletException {
    
            FilterInvocation fi = new FilterInvocation(request, response,chain);
            invoke(fi);
        }
    
        @Override
        public void destroy() {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public Class<?> getSecureObjectClass() {
            // TODO Auto-generated method stub
            return FilterInvocation.class;
        }
    
        @Override
        public SecurityMetadataSource obtainSecurityMetadataSource() {
            // TODO Auto-generated method stub
            return this.securityMetadataSource;
        }
    
        public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
            return securityMetadataSource;
        }
    
        public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource securityMetadataSource) {
            this.securityMetadataSource = securityMetadataSource;
        }
    
        public void invoke(FilterInvocation fi) throws IOException
            ,ServletException{
            
            InterceptorStatusToken token = super.beforeInvocation(fi);
            try {
                fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
            } catch (Exception e) {
                // TODO: handle exception
            }finally{
                super.afterInvocation(token, null);
            }
        }
    }

    6.DefaultUserDetailsService的实现

    在这个类中你可以通过读取数据库来进行权限赋值,下面的代码未注解的是我写的静态的

    package com.demo.im.model.security;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    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.demo.im.entity.Role;
    import com.demo.im.entity.TUser;
    import com.demo.im.model.dao.TUserMapper;
    @Service
    public class DefaultUserDetailsService implements UserDetailsService {
        @Autowired
        TUserMapper userDao;
        
        @Override
        public UserDetails loadUserByUsername(String username)
                throws UsernameNotFoundException {
            // TODO Auto-generated method stub
            System.out.println("userDetail********");
            Collection <GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
            
            GrantedAuthority auth2 = new GrantedAuthorityImpl("ROLE_ADMIN");
            
            auths.add(auth2);
            
            User user = new User(username,"1111",true,true,true,true,auths);
            return user;
            
            
    //        TUser paramU = new TUser();
    //        paramU.setUsername(username);
    //        List<TUser> userList = userDao.selectByUserParam(paramU);
    //        TUser user = new TUser();
    //        if(userList==null || userList.size()<=0){
    //            throw new UsernameNotFoundException("username");
    //        }
    //        //得到用户权限
    //        if(user.getRoles()!=null && user.getRoles().size()>0){
    //            
    //            for(Role role : user.getRoles()){
    //                GrantedAuthority grantedAuthority = new GrantedAuthorityImpl(
    //                        role.getRolecode().toUpperCase());
    //                auths.add(grantedAuthority);
    //            }
    //            
    //        }
    //        user.setAuthorities(auths);
    //        return user;
        }
    
    }

    7.MyInvocationSecurityMetadaSource类的内容

    这个类说白了就是从数据库中取出资源对应的权限,我这里也是写的静态的,修改为动态的方法也很简单,执行一个查询就行了

    package com.demo.im.model.security;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    
    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;
    
    public class MyInvocationSecurityMetadaSource 
        implements FilterInvocationSecurityMetadataSource{
    
    //    private UrlMatcher urlMatcher = new AntUrlPathMatcher();
        private static Map<String,Collection<ConfigAttribute>> resourceMap = null;
        
        public MyInvocationSecurityMetadaSource(){
            loadResourceDefine();
        }
        
        private void loadResourceDefine(){
            resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
            Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
            
            ConfigAttribute ca = new SecurityConfig("ROLE_ADMIN");
            
            atts.add(ca);
            resourceMap.put("/user.jsp", atts);
            resourceMap.put("/admin.jsp", atts);
            resourceMap.put("/index.jsp",atts);
            
        }
        
        @Override
        public Collection<ConfigAttribute> getAttributes(Object object)
                throws IllegalArgumentException {
            // TODO Auto-generated method stub
            String url = ((FilterInvocation)object).getRequestUrl();
            Iterator<String> ite = resourceMap.keySet().iterator();
            
            while(ite.hasNext()){
                String resURL = ite.next();
                
                if(url.equalsIgnoreCase(resURL)){
                    return resourceMap.get(resURL);
                }
                
            }
            
            return null;
        }
    
        @Override
        public Collection<ConfigAttribute> getAllConfigAttributes() {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public boolean supports(Class<?> clazz) {
            // TODO Auto-generated method stub
            return true;
        }
    
    }

    8.最后就是决策类了MyAccessDecisionManager

    这个类就更好理解了,我们知道了用户的角色,我们也知道资源的角色,对比一下,也就是decide()一致就返回,不行就抛异常

    package com.demo.im.model.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.access.SecurityConfig;
    import org.springframework.security.authentication.InsufficientAuthenticationException;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.GrantedAuthority;
    
    public class MyAccessDecisionManager implements AccessDecisionManager{
    
        @Override
        public void decide(Authentication authentication, Object object,
                Collection<ConfigAttribute> configAttributes) throws AccessDeniedException,
                InsufficientAuthenticationException {
            if(configAttributes  == null){
                return ;
            }
            System.out.println(object.toString());
            Iterator<ConfigAttribute> ite = configAttributes.iterator();
            while(ite.hasNext()){
                ConfigAttribute ca = ite.next();
                String needRole = ((SecurityConfig)ca).getAttribute();
                
                for(GrantedAuthority ga : authentication.getAuthorities()){
                    if(needRole.equals(ga.getAuthority())){
                        return ;
                    }
                }
            }
            throw new AccessDeniedException("no right");
            
        }
    
        @Override
        public boolean supports(ConfigAttribute arg0) {
            // TODO Auto-generated method stub
            return true;
        }
    
        @Override
        public boolean supports(Class<?> arg0) {
            // TODO Auto-generated method stub
            return true;
        }
    
    }

    9总结:

    到这里一个基本的spring  security算是搭建完了。过会在来说说我遇到的坑。方便以后大家找自己的坑。

  • 相关阅读:
    Visifire正式版(v1.1)发布
    [转]PSP机能强大!已能模拟运行WINDOWS系统?
    在Silverlight+WCF中应用以角色为基础的安全模式(一)基础篇之角色为基础的安全模式简介 Virus
    C#的加密解密算法,包括Silverlight的MD5算法 Virus
    MMORPG programming in Silverlight Tutorial (10)Implement the sprite’s 2D animation (Part IV)
    Game Script: Rescue Bill Gates
    MMORPG programming in Silverlight Tutorial (9)KeyFrame Animation
    MMORPG programming in Silverlight Tutorial (5)Implement the sprite’s 2D animation (Part II)
    MMORPG programming in Silverlight Tutorial (7)Perfect animation
    MMORPG programming in Silverlight Tutorial (3)Animate the object (Part III)
  • 原文地址:https://www.cnblogs.com/wangxiangstudy/p/5961118.html
Copyright © 2011-2022 走看看