Spring security 3


最近ずっとspring security 3を勉強しています。環境を作ってみました。
  • maven環境を構築する
  • Spring security3_第1张图片
    プロジェクト設定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/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.github.humeng126</groupId>
        <artifactId>security-07</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>war</packaging>
    
        <name>security-07</name>
        <url>http://maven.apache.org</url>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <springsecurity.version>3.2.3.RELEASE</springsecurity.version>
            <spring.version>4.0.3.RELEASE</spring.version>
            <mysql-connector.version>5.1.30</mysql-connector.version>
        </properties>
    
        <dependencies>
            <!-- web begin -->
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>jstl</artifactId>
                <version>1.2</version>
            </dependency>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>servlet-api</artifactId>
                <version>2.5</version>
                <scope>provided</scope>
            </dependency>
            <!-- web end -->
    
            <!-- spring begin -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context-support</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aop</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjrt</artifactId>
                <version>1.6.9</version>
            </dependency>
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.6.9</version>
            </dependency>
            <dependency>
                <groupId>cglib</groupId>
                <artifactId>cglib</artifactId>
                <version>2.2.2</version>
            </dependency>
            <dependency>
                <groupId>asm</groupId>
                <artifactId>asm</artifactId>
                <version>3.3.1</version>
            </dependency>
            <!-- spring end -->
    
            <!-- security begin -->
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-core</artifactId>
                <version>${springsecurity.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-taglibs</artifactId>
                <version>${springsecurity.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-config</artifactId>
                <version>${springsecurity.version}</version>
            </dependency>
            <!-- security end -->
    
            <!-- pool begin -->
            <dependency>
                <groupId>commons-dbcp</groupId>
                <artifactId>commons-dbcp</artifactId>
                <version>1.4</version>
            </dependency>
            <!-- pool end -->
    
            <!-- connector begin -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql-connector.version}</version>
            </dependency>
            <!-- connector end -->
    
            <!-- test begin -->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</version>
            </dependency>
            <!-- test end -->
    
            <!-- cache begin -->
            <dependency>
                <groupId>net.sf.ehcache</groupId>
                <artifactId>ehcache-core</artifactId>
                <version>2.6.9</version>
            </dependency>
            <!-- cache end -->
        </dependencies>
    </project>
  • で、web.xmlプロファイルにfilter
  • を追加します。
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
        version="2.5">
        <display-name>security-01</display-name>
    
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext*.xml</param-value>
        </context-param>
    
        <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>
    
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
    
    </web-app>
  • springのaplication Contact.xml追加権限構成
    <?xml version="1.0" encoding="UTF-8"?>
    <!--    xml   Spring Security        -->
    <b:beans xmlns="http://www.springframework.org/schema/security"
        xmlns:b="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">
    
        <!--     custom-filter  ,    filterSecurityInterceptor       FILTER_SECURITY_INTERCEPTOR     , 
                               ,               ,                  -->
        <http auto-config='true' access-denied-page="/accessDenied.jsp">
            <custom-filter ref="filterSecurityInterceptor" before="FILTER_SECURITY_INTERCEPTOR" />
        </http>
    
        <!-- users-by-username-query          ,                    ,            。authorities-by-username-query          ,                          -->
        <authentication-manager>
            <authentication-provider>
                <!--   MD5   -->
                <password-encoder hash="md5">
                    <!--     : password-encoder    salt-source,      username     -->
                    <salt-source user-property="username"/>
                </password-encoder>
                <jdbc-user-service data-source-ref="dataSource"
                    cache-ref="userCache"
                    users-by-username-query="select username,password,status as enabled
                                             from user
                                            where username=?"
                    authorities-by-username-query="select u.username,r.name as authority
                                                 from user u
                                                 join user_role ur
                                                   on u.id=ur.user_id
                                                 join role r
                                                   on r.id=ur.role_id
                                                where u.username=?" />
            </authentication-provider>
        </authentication-manager>
    
        <!--   begin -->
        <b:bean id="userCache"
            class="org.springframework.security.core.userdetails.cache.EhCacheBasedUserCache">
            <b:property name="cache" ref="userEhCache" />
        </b:bean>
    
        <b:bean id="userEhCache"
            class="org.springframework.cache.ehcache.EhCacheFactoryBean">
            <b:property name="cacheManager" ref="cacheManager" />
            <b:property name="cacheName" value="userCache" />
        </b:bean>
    
        <b:bean id="cacheManager"
            class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" />
        <!--   end -->
    
        <b:bean id="filterSecurityInterceptor"
            class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor"
            autowire="byType">
            <b:property name="securityMetadataSource" ref="filterInvocationSecurityMetadataSource" />
            <b:property name="authenticationManager"
                ref="org.springframework.security.authenticationManager" />
        </b:bean>
    
        <b:bean id="filterInvocationSecurityMetadataSource"
            class="com.github.humeng126.security_01.JdbcFilterInvocationDefinitionSourceFactoryBean">
            <b:property name="dataSource" ref="dataSource" />
            <b:property name="resourceQuery"
                value="
                select re.res_string,r.name
                  from role r
                  join resc_role rr
                    on r.id=rr.role_id
                  join resc re
                    on re.id=rr.resc_id
              order by re.priority
            " />
        </b:bean>
    
        <b:bean id="propertyConfigurer"
            class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <b:property name="locations">
                <b:list>
                    <b:value>classpath*:application.properties</b:value>
                </b:list>
            </b:property>
        </b:bean>
        <!--      ,   DBCP       -->
        <b:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
            destroy-method="close">
            <!-- Connection Info -->
            <b:property name="driverClassName" value="${jdbc.driver}" />
            <b:property name="url" value="${jdbc.url}" />
            <b:property name="username" value="${jdbc.username}" />
            <b:property name="password" value="${jdbc.password}" />
    
            <!-- Connection Pooling Info -->
            <b:property name="maxActive" value="${dbcp.maxActive}" />
            <b:property name="maxIdle" value="${dbcp.maxIdle}" />
            <b:property name="defaultAutoCommit" value="false" />
            <!--   Idle        -->
            <b:property name="timeBetweenEvictionRunsMillis" value="3600000" />
            <b:property name="minEvictableIdleTimeMillis" value="3600000" />
        </b:bean>
    </b:beans>
  •  
  • データベーステーブル
  • 表の基本情報は、業務システムが自分のニーズに応じて柔軟にカスタマイズできます。
    --   
    create table resc(
        id bigint,
        name varchar(50),
        res_type varchar(50),
        res_string varchar(200),
        priority integer,
        descn varchar(200)
    );
    alter table resc add constraint pk_resc primary key(id);
    alter table resc alter column id bigint generated by default as identity(start with 1);
    
    --   
    create table role(
        id bigint,
        name varchar(50),
        descn varchar(200)
    );
    alter table role add constraint pk_role primary key(id);
    alter table role alter column id bigint generated by default as identity(start with 1);
    
    --   
    create table user(
        id bigint,
        username varchar(50),
        password varchar(50),
        status integer,
        descn varchar(200)
    );
    alter table user add constraint pk_user primary key(id);
    alter table user alter column id bigint generated by default as identity(start with 1);
    
    --        
    create table resc_role(
        resc_id bigint,
        role_id bigint
    );
    alter table resc_role add constraint pk_resc_role primary key(resc_id, role_id);
    alter table resc_role add constraint fk_resc_role_resc foreign key(resc_id) references resc(id);
    alter table resc_role add constraint fk_resc_role_role foreign key(role_id) references role(id);
    
    --        
    create table user_role(
        user_id bigint,
        role_id bigint
    );
    alter table user_role add constraint pk_user_role primary key(user_id, role_id);
    alter table user_role add constraint fk_user_role_user foreign key(user_id) references user(id);
    alter table user_role add constraint fk_user_role_role foreign key(role_id) references role(id);
    Spring security3_第2张图片
    insert into user(id,username,password,status,descn) values(1,'admin','admin',1,'   ');
    insert into user(id,username,password,status,descn) values(2,'user','user',1,'  ');
    
    insert into role(id,name,descn) values(1,'ROLE_ADMIN','     ');
    insert into role(id,name,descn) values(2,'ROLE_USER','    ');
    
    insert into resc(id,name,res_type,res_string,priority,descn) values(1,'','URL','/admin.jsp',1,'');
    insert into resc(id,name,res_type,res_string,priority,descn) values(2,'','URL','/**',2,'');
    
    insert into resc_role(resc_id,role_id) values(1,1);
    insert into resc_role(resc_id,role_id) values(2,1);
    insert into resc_role(resc_id,role_id) values(2,2);
    
    insert into user_role(user_id,role_id) values(1,1);
    insert into user_role(user_id,role_id) values(1,2);
    insert into user_role(user_id,role_id) values(2,2);
  • パーミッションフィルタ
  • package com.github.humeng126.security_01;
    
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.Collection;
    import java.util.LinkedHashMap;
    import java.util.List;
    import java.util.Map;
    
    import javax.sql.DataSource;
    
    import org.springframework.beans.factory.FactoryBean;
    import org.springframework.jdbc.core.support.JdbcDaoSupport;
    import org.springframework.jdbc.object.MappingSqlQuery;
    import org.springframework.security.access.ConfigAttribute;
    import org.springframework.security.access.ConfigAttributeEditor;
    import org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource;
    import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
    import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
    import org.springframework.security.web.util.matcher.RequestMatcher;
    
    public class JdbcFilterInvocationDefinitionSourceFactoryBean extends
            JdbcDaoSupport implements FactoryBean {
    
        private String resourceQuery;
    
        public Object getObject() throws Exception {
            return new DefaultFilterInvocationSecurityMetadataSource(
                    this.buildRequestMap());
        }
    
        public Class getObjectType() {
            return FilterInvocationSecurityMetadataSource.class;
        }
    
        public boolean isSingleton() {
            return true;
        }
    
        protected Map<String, String> findResources() {
            ResourceMapping resourceMapping = new ResourceMapping(getDataSource(),
                    resourceQuery);
            Map<String, String> resourceMap = new LinkedHashMap<String, String>();
            //     execute()          
            for (Resource resource : (List<Resource>) resourceMapping.execute()) {
                String url = resource.getUrl();
                String role = resource.getRole();
                if (resourceMap.containsKey(url)) {
                    String value = resourceMap.get(url);
                    resourceMap.put(url, value + "," + role);
                } else {
                    resourceMap.put(url, role);
                }
            }
            return resourceMap;
        }
    
        protected LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> buildRequestMap() {
            LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap = null;
            requestMap = new LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>>();
            ConfigAttributeEditor editor = new ConfigAttributeEditor();
            Map<String, String> resourceMap = this.findResources();
            //   urlMatcher requestMap  DefaultFilterInvocationDefinitionSource
            for (Map.Entry<String, String> entry : resourceMap.entrySet()) {
                String key = entry.getKey();
                editor.setAsText(entry.getValue());
                requestMap.put(new AntPathRequestMatcher(key),
                        (Collection<ConfigAttribute>) editor.getValue());
            }
            return requestMap;
        }
    
        //       MappingSqlQuery       
        private class ResourceMapping extends MappingSqlQuery {
            protected ResourceMapping(DataSource dataSource, String resourceQuery) {
                super(dataSource, resourceQuery);
                compile();
            }
    
            protected Object mapRow(ResultSet rs, int rownum) throws SQLException {
                String url = rs.getString(1);
                String role = rs.getString(2);
                Resource resource = new Resource(url, role);
                return resource;
            }
        }
    
        private class Resource {
            private String url;
            private String role;
    
            public Resource(String url, String role) {
                this.url = url;
                this.role = role;
            }
    
            public String getUrl() {
                return url;
            }
    
            public String getRole() {
                return role;
            }
        }
    
        public String getResourceQuery() {
            return resourceQuery;
        }
    
        public void setResourceQuery(String resourceQuery) {
            this.resourceQuery = resourceQuery;
        }
    
    }
  • 権限を変更し、ページ
  • を動的に更新する。
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <%@page import="org.springframework.context.ApplicationContext"%>
    <%@page
        import="org.springframework.web.context.support.WebApplicationContextUtils"%>
    <%@page import="org.springframework.beans.factory.FactoryBean"%>
    <%@page
        import="org.springframework.security.web.access.intercept.FilterSecurityInterceptor"%>
    <%@page
        import="org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource"%>
    <%
        ApplicationContext ctx = WebApplicationContextUtils
                .getWebApplicationContext(application);
        FactoryBean factoryBean = (FactoryBean) ctx
                .getBean("&filterInvocationSecurityMetadataSource");
        FilterInvocationSecurityMetadataSource fids = (FilterInvocationSecurityMetadataSource) factoryBean
                .getObject();
        FilterSecurityInterceptor filter = (FilterSecurityInterceptor) ctx
                .getBean("filterSecurityInterceptor");
        filter.setSecurityMetadataSource(fids);
    %>
    <jsp:forward page="/" />
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title></title>
    </head>
    <body>
    
    </body>
    </html>