zoukankan      html  css  js  c++  java
  • spring security demo

    该demo利用maven管理:

    pom.xml如下:

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>com</groupId>
      <artifactId>SP</artifactId>
      <packaging>war</packaging>
      <version>0.0.1-SNAPSHOT</version>
      <name>SP Maven Webapp</name>
      <url>http://maven.apache.org</url>
      <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>3.8.1</version>
          <scope>test</scope>
        </dependency>
        
        <dependency>
           <groupId>commons-fileupload</groupId>
           <artifactId>commons-fileupload</artifactId>
           <version>1.2.2</version>
         </dependency>
         
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>4.3.8.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework.data</groupId>
          <artifactId>spring-data-jpa</artifactId>
          <version>1.11.3.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework.security</groupId>
          <artifactId>spring-security-web</artifactId>
          <version>4.0.4.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework.security</groupId>
          <artifactId>spring-security-config</artifactId>
          <version>4.0.4.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>jstl</artifactId>
          <version>1.2</version>
        </dependency>
        
        <dependency>
          <groupId>commons-httpclient</groupId>
          <artifactId>commons-httpclient</artifactId>
          <version>2.0.2</version>
        </dependency>
        
        <dependency>
          <groupId>net.sf.json-lib</groupId>
          <artifactId>json-lib</artifactId>
          <version>2.4</version>
          <classifier>jdk15</classifier>
        </dependency>
            
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.3.11.Final</version>
          <exclusions>
            <exclusion>
              <artifactId>xml-apis</artifactId>
              <groupId>xml-apis</groupId>
            </exclusion>
          </exclusions>
        </dependency>
        <dependency>
          <groupId>org.hibernate</groupId>
          <artifactId>hibernate-entitymanager</artifactId>
          <version>4.3.11.Final</version>
        </dependency>
    
        <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-api</artifactId>
          <version>1.7.25</version>
        </dependency>
        <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-log4j12</artifactId>
          <version>1.7.25</version>
        </dependency>
        <dependency>
          <groupId>log4j</groupId>
          <artifactId>log4j</artifactId>
          <version>1.2.17</version>
        </dependency>
        <dependency>
          <groupId>com.oracle</groupId>
          <artifactId>ojdbc6</artifactId>
          <version>11.2.0.4</version>
        </dependency>
    
        <dependency>
          <groupId>commons-dbcp</groupId>
          <artifactId>commons-dbcp</artifactId>
          <version>1.4</version>
        </dependency>
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>servlet-api</artifactId>
          <version>2.5</version>
          <scope>provided</scope>
        </dependency>
        <dependency>
          <groupId>commons-io</groupId>
          <artifactId>commons-io</artifactId>
          <version>2.4</version>
        </dependency>
        <dependency>
          <groupId>org.apache.commons</groupId>
          <artifactId>commons-lang3</artifactId>
          <version>3.1</version>
        </dependency>
        <dependency>
          <groupId>commons-net</groupId>
          <artifactId>commons-net</artifactId>
          <version>3.6</version>
        </dependency>
        <dependency>
          <groupId>net.sf.ehcache</groupId> 
          <artifactId>ehcache-web</artifactId>
          <version>2.0.4</version>
        </dependency> 
        <dependency>
          <groupId>net.sf.ehcache</groupId>
          <artifactId>ehcache</artifactId>
          <version>2.8.3</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context-support</artifactId>
          <version>4.3.8.RELEASE</version>
        </dependency>
        <dependency>
             <groupId>org.springframework.ws</groupId>
             <artifactId>spring-ws-core</artifactId>
             <version>2.1.3.RELEASE</version>
         </dependency>
      </dependencies>
      <build>
        <finalName>SystemManage</finalName>
        <defaultGoal>compile</defaultGoal>
        <resources>
          <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
          </resource>
        </resources>
        <plugins>
          <!-- 编译配置 -->
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
              <source>${java.version}</source>
              <target>${java.version}</target>
            </configuration>
          </plugin>
          <!--Tomcat 配置-->
          <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.1</version>
            <configuration>
              <path>/SystemManage</path>
              <port>8081</port>
              <uriEncoding>UTF-8</uriEncoding>
              <server>tomcat7</server>
            </configuration>
          </plugin>
          <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-resources-plugin</artifactId>
              <version>2.6</version>
              <configuration>
                  <encoding>UTF-8</encoding>
              </configuration>
          </plugin>
        </plugins>
      </build>
    </project>
    pom.xml

    配置文件:

    首先过滤出项目的登陆页,

    访问该项目的用户需要有'ROLE_USER'的角色,controller中定义@RequestMapping(value = "/loginPage", method = RequestMethod.GET)的登录页。

    login-processing-url必须要和登录页面中的表单提交路径相同。

    authentication-success-handler-ref配置登陆成功后的处理bean

    authentication-faliure-url登陆失败后的跳转页面

    logout-url: 登出,必须要和登出的链接相同;

    invalidate-session:是否销毁session;

    登陆验证:UserDetailService和PasswordEncoder

    MyUserDetailService.java
    package com.yin.myproject.security.controller;
    
    import java.util.ArrayList;
    import java.util.List;
    
    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;
    
    public class MyUserDetailService implements UserDetailsService{
    
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            //权限
            List<SimpleGrantedAuthority> roles = new ArrayList<SimpleGrantedAuthority>();
            roles.add(new SimpleGrantedAuthority("ROLE_USER"));
            
            return new User(username,username,roles);
        }
    
    }
    MyPasswordEncoder .java
    package com.yin.myproject.security.controller;
    
    import org.springframework.security.crypto.password.PasswordEncoder;
    
    public class MyPasswordEncoder implements PasswordEncoder{
    
        public String encode(CharSequence rawPassword) {
            String encPassword = rawPassword.toString();
            return encPassword;
        }
    
        public boolean matches(CharSequence rawPassword, String encodedPassword) {
            return encode(rawPassword).equals(encodedPassword);
        }
    
    
    }

    验证成功后,进入处理登陆成功的bean

    LoginSuccessHandler.java
    package com.yin.myproject.security.controller;
    
    import java.io.IOException;
    import java.util.Collection;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.userdetails.User;
    import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
    
    public class LoginSuccessHandler implements AuthenticationSuccessHandler{
    
        public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                Authentication authentication) throws IOException, ServletException {
            Object principal = authentication.getPrincipal();
            User user = (User) principal;
            Collection<GrantedAuthority> authorities = user.getAuthorities();
            for (GrantedAuthority authority : authorities) {
                if (authority.getAuthority().equals("ROLE_USER")) {
                    HttpSession session = request.getSession();
                    session.setAttribute("role", "ROLE_USER");
                    //再将用户保存在session中
                    response.sendRedirect(request.getContextPath() + "/welcome");
                }
            }
        }
    }

    权限控制重点记录(见下文)。

    <?xml version="1.0" encoding="UTF-8"?>
    <bean:beans xmlns="http://www.springframework.org/schema/security"
        xmlns:bean="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.xsd
                            http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
    
        <http pattern="/loginPage" security="none"></http>
    
        <http auto-config="true" use-expressions="true">
            <intercept-url pattern="/*" access="hasRole('ROLE_USER')" />
            <form-login login-page="/loginPage" login-processing-url="/login"
                authentication-success-handler-ref="mySuccessHandler"
                authentication-failure-url="/loginPage?error=error" />
            <logout logout-url="/logout" logout-success-url="/loginPage" invalidate-session="true"/>
            <remember-me key="authorition" use-secure-cookie="true"/>
    <!--         权限控制 -->
            <custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR"/>
            <csrf disabled="true" />
        </http>
        <authentication-manager alias="authenticationManager">
            <authentication-provider user-service-ref="myUserDetailService">
    <!--             <user-service> -->
    <!--                 <user authorities="ROLE_USER" name="guest" password="guest" /> -->
    <!--             </user-service> -->
        <!-- 密码加密 -->  
                       <password-encoder ref="myPasswordEncoder"/>
            </authentication-provider>
        </authentication-manager>
    
        <bean:bean id="myUserDetailService" class="com.yin.myproject.security.controller.MyUserDetailService"></bean:bean>
    
        <bean:bean id="myPasswordEncoder" class="com.yin.myproject.security.controller.MyPasswordEncoder"></bean:bean>
        
        <bean:bean id="mySuccessHandler" class="com.yin.myproject.security.controller.LoginSuccessHandler"></bean:bean>
        
    <!--     权限控制过滤器 -->
        <bean:bean id="myFilter" class="com.yin.myproject.security.controller.MyfilterSecurityInterceptor"> 
                 <bean:property name="accessDecisionManager" ref="accessDecisionManager"></bean:property> 
                 <bean:property name="securityMetadataSourceService" ref="securityMetadataSourceService"></bean:property>
         </bean:bean> 
         
         <!--         投票规则 -->
            <bean:bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">  
                <bean:constructor-arg name="decisionVoters">  
                    <bean:list>  
    <!--                      <ref bean="roleVoter"/>    -->
    <!--                      <ref bean="authenticatedVoter"/>    -->
                        <bean:ref bean="defaultVoter" />
                    </bean:list>  
                </bean:constructor-arg>  
            </bean:bean>
    <!--         自定义投票器 -->
            <bean:bean id="defaultVoter" class="com.yin.myproject.security.controller.DefaultVoter"></bean:bean>
            
            
            <bean:bean id="securityMetadataSourceService" class="com.yin.myproject.security.controller.MyInvocationSecurityMetadataSourceService"></bean:bean>
    </bean:beans>

    重点记录权限配置:

    配置文件中定义过滤器myfilter用来做权限,这个过滤器在spring security的FILTER_SECURITY_INTERCEPTOR之前。

    MyfilterSecurityInterceptor.java
    package com.yin.myproject.security.controller;
    
    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 MyfilterSecurityInterceptor extends AbstractSecurityInterceptor  implements Filter{
    
        private FilterInvocationSecurityMetadataSource securityMetadataSourceService;
        
        public void init(FilterConfig filterConfig) throws ServletException {
            // TODO Auto-generated method stub
            
        }
    
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            FilterInvocation fi = new FilterInvocation(request, response, chain);   
            invoke(fi);
        }
    
        public void destroy() {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public Class<?> getSecureObjectClass() {
            return FilterInvocation.class;
        }
    
        @Override
        public SecurityMetadataSource obtainSecurityMetadataSource() {
            return this.securityMetadataSourceService;
        }
        
        public void invoke(FilterInvocation fi) throws IOException, ServletException {  
            //fi里面有一个被拦截的url  
            //里面调用MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法获取fi对应的所有权限  
            //再调用MyAccessDecisionManager的decide方法来校验用户的权限是否足够  
            InterceptorStatusToken token = super.beforeInvocation(fi);  
            try {  
                //执行下一个拦截器  
                fi.getChain().doFilter(fi.getRequest(), fi.getResponse());     
                } finally {   
                    super.afterInvocation(token, null);    
                }     
        }
        
        public FilterInvocationSecurityMetadataSource getSecurityMetadataSourceService() {
            return securityMetadataSourceService;
        }
    
        public void setSecurityMetadataSourceService(
                FilterInvocationSecurityMetadataSource securityMetadataSourceService) {
            this.securityMetadataSourceService = securityMetadataSourceService;
        }  
    
    }

    在这个bean中配置属性accessDecisionManagersecurityMetadataSourceService,这两个bean分别定义了权限采用的投票规则初始化访问的链接和访问它所需要权限的对应关系

    MyInvocationSecurityMetadataSourceService.java
    package com.yin.myproject.security.controller;
    
    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.springframework.beans.factory.InitializingBean;
    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 MyInvocationSecurityMetadataSourceService implements FilterInvocationSecurityMetadataSource,InitializingBean{
    
        private static Map<String, Collection<ConfigAttribute>> resourceMap = null; 
        
        //初始化链接和权限的关系
        private void loadResourceDefine(){
            resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
            
            //得到所有权限
            String tempAuth = "ROLE_USER";
            List<String> auths = new ArrayList<String>();
            //得到链接
            List<String> urls = new ArrayList<String>();
            auths.add(tempAuth);
            
            for(String auth:auths){
                ConfigAttribute ca = new SecurityConfig(auth);
                
                String tempUrl = "/welcome" ;
                urls.add(tempUrl);
                for(String url:urls){
                    if(resourceMap.containsKey(url)){
                        Collection<ConfigAttribute> value = resourceMap.get(url);
                        value.add(ca);
                        resourceMap.put(url, value);
                    }else{
                        Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
                        atts.add(ca);
                        resourceMap.put(url, atts);
                    }
                }
                
            }
        }
        
        public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
            String url = ((FilterInvocation) object).getRequestUrl();
            int firstQuestionMarkIndex = url.indexOf("?");
            if (firstQuestionMarkIndex != -1) {
                url = url.substring(0, firstQuestionMarkIndex);
            }
            Iterator<String> ite = resourceMap.keySet().iterator();
            while (ite.hasNext()) {
                String resURL = ite.next();
    
                if (url.equals(resURL)) {
    
                    return resourceMap.get(resURL);
                }
            }
    
            return null;
        }
    
        public Collection<ConfigAttribute> getAllConfigAttributes() {
            return null;
        }
    
        public boolean supports(Class<?> clazz) {
            return true;
        }
    
        //bean加载后初始化
        public void afterPropertiesSet() throws Exception {
            loadResourceDefine();
        }
    
    }

    defaultVoter是自定义的投票器。它需要添加在投票规则中。

    DefaultVoter.java
    package com.yin.myproject.security.controller;
    
    import java.util.Collection;
    
    import org.springframework.security.access.AccessDecisionVoter;
    import org.springframework.security.access.ConfigAttribute;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.GrantedAuthority;
    
    public class DefaultVoter implements AccessDecisionVoter<Object>{
    
        public boolean supports(ConfigAttribute attribute) {
            return true;
        }
    
        public boolean supports(Class<?> clazz) {
            return true;
        }
    
        public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
            int result = ACCESS_ABSTAIN;
            Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
            for (ConfigAttribute attribute : attributes) {  
                if (this.supports(attribute)) {  
                    result = ACCESS_DENIED;  
          
                    // Attempt to find a matching granted authority  
                    for (GrantedAuthority authority : authorities) {  
                        if (attribute.getAttribute().equals(authority.getAuthority())) {  
                            return ACCESS_GRANTED;  
                        }  
                    }  
                }  
            }  
          
            return result;
        }
        
    }

     代码下载:

    https://i.cnblogs.com/Files.aspx中的SP.rar

    下图记录一个描述spring-security的流程图:

  • 相关阅读:
    连接H3C交换机的Console口连不上
    WIN7远程桌面连接--“发生身份验证错误。要求的函数不受支持”
    关于SSD Trim功能
    电源适配器和充电器的区别和关系
    处理win7任务栏通知区域图标异常问题
    VMware Workstation 学习笔记
    关于“找不到附属汇编 Microsoft.VC90.CRT,上一个错误是 参照的汇编没有安装在系统上。”的解决
    Win7硬盘的AHCI模式
    电脑没有网络的故障分析
    通过Performance Log确定磁盘有性能问题?
  • 原文地址:https://www.cnblogs.com/popcornya/p/7738465.html
Copyright © 2011-2022 走看看