Spring Security3实现,权限动态获取

采用Maven管理,Spring Mvc Jpa等技术

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.wiker</groupId>
<artifactId>springSecurity</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>springSecurity Maven Webapp</name>
<url>http://maven.apache.org</url> <properties>
<!-- 主要依赖库的版本定义 -->
<c3p0.version>0.9.1.2</c3p0.version>
<spring-hibernate3.version>2.0.8</spring-hibernate3.version>
<javax.transaction.version>1.1</javax.transaction.version>
<org.kohsuke.stapler.version>2.1-rev6</org.kohsuke.stapler.version>
<spring-web.version>3.2.3.RELEASE</spring-web.version>
<commons-lang.version>2.5</commons-lang.version>
<javax.xml.rpc.version>1.1</javax.xml.rpc.version>
<commons-email.version>1.1</commons-email.version>
<org.apache.axis.version>1.4</org.apache.axis.version>
<commons-fileupload.version>1.3</commons-fileupload.version>
<jdom.version>1.1</jdom.version>
<javax.servlet.jstl.version>1.2</javax.servlet.jstl.version>
<javax.servlet.api.version>2.5</javax.servlet.api.version>
<jxl.version>2.6.12</jxl.version>
<javax.activation.version>1.1.1</javax.activation.version>
<javax.mail.version>1.4.5</javax.mail.version>
<spring.version>3.2.3.RELEASE</spring.version>
<hibernate.version>4.1.8.Final</hibernate.version>
<hibernate.core.version>4.1.8.Final</hibernate.core.version>
<spring-data-jpa.version>1.2.0.RELEASE</spring-data-jpa.version>
<commons-dbcp.version>1.4</commons-dbcp.version>
<sitemesh.version>2.4.2</sitemesh.version>
<hibernate-validator.version>4.3.0.Final</hibernate-validator.version>
<jackson.version>2.1.2</jackson.version>
<jackson-asl.version>1.9.5</jackson-asl.version>
<slf4j.version>1.7.2</slf4j.version>
<log4j.version>1.2.17</log4j.version>
<commons-lang3.version>3.1</commons-lang3.version>
<guava.version>13.0.1</guava.version>
<quartz.version>1.5.2</quartz.version>
<freemarker.version>2.3.19</freemarker.version>
<httpclient.version>4.2.2</httpclient.version>
<commons-httpclient.version>3.0.1</commons-httpclient.version>
<joda-time.version>2.1</joda-time.version>
<junit.version>4.11</junit.version>
<testng.version>6.3</testng.version>
<mockito.version>1.9.5</mockito.version>
<selenium.version>2.28.0</selenium.version>
<jetty.version>7.6.8.v20121106</jetty.version>
<h2.version>1.3.170</h2.version>
<codec.version>1.6</codec.version>
<dom4j.version>1.6.1</dom4j.version>
<lombok.version>0.11.0</lombok.version>
<wro4j.version>1.4.7</wro4j.version>
<wro4j.extensions.version>1.4.7</wro4j.extensions.version>
<commons-io.version>2.4</commons-io.version>
<commons-collections.version>3.2.1</commons-collections.version>
<gson.version>2.2.2</gson.version>
<pinyin4j.version>2.5.0</pinyin4j.version>
<wicked-charts.version>1.4.3</wicked-charts.version>
<batik-all.version>1.8pre-r1084380</batik-all.version>
<rhino.version>1.7R4</rhino.version>
<thumbnailator.version>[0.4, 0.5)</thumbnailator.version>
<struts2.core.version>2.3.14.3</struts2.core.version>
<wsdl4j.version>1.5.1</wsdl4j.version>
<aspectjrt.version>1.7.1</aspectjrt.version>
<velocity.version>1.7</velocity.version>
<antlr.version>2.7.6</antlr.version>
<jchardet.version>1.0</jchardet.version>
<google-collection.version>1.0</google-collection.version>
<json-lib.version>2.4</json-lib.version>
<urlrewritefilter.version>4.0.3</urlrewritefilter.version> <!-- Plugin的属性定义 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jdk.version>1.6</jdk.version> <server.url>http://localhost:8080/manager/html</server.url>
<server.user>admin</server.user>
<server.password>admin</server.password> <jdbc.driver.groupId>mysql</jdbc.driver.groupId>
<jdbc.driver.artifactId>mysql-connector-java</jdbc.driver.artifactId>
<jdbc.driver.version>5.1.21</jdbc.driver.version>
</properties>
<dependencies>
<dependency>
<groupId>com.google.collections</groupId>
<artifactId>google-collections</artifactId>
<version>${google-collection.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- <dependency> <groupId>org.apache.axis2</groupId> <artifactId>axis2</artifactId>
<version>${org.apache.axis2.version}</version> </dependency> -->
<dependency>
<groupId>org.apache.axis</groupId>
<artifactId>axis</artifactId>
<version>${org.apache.axis.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>${commons-lang.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency> <!-- Spring Security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>3.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.18</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>3.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>3.1.4.RELEASE</version>
</dependency> <dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectjrt.version}</version>
</dependency>
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j-qname</artifactId>
<version>${wsdl4j.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectjrt.version}</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
<version>3.3.1</version>
<scope>runtime</scope>
</dependency> <dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.core.version}</version>
</dependency>
<dependency>
<groupId>javax.xml.rpc</groupId>
<artifactId>javax.xml.rpc-api</artifactId>
<version>${javax.xml.rpc.version}</version>
</dependency>
<!-- spring data access -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>${spring-data-jpa.version}</version>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit-dep</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>${json-lib.version}</version>
<classifier>jdk15</classifier>
</dependency>
<dependency>
<groupId>org.tuckey</groupId>
<artifactId>urlrewritefilter</artifactId>
<version>${urlrewritefilter.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.2</version>
</dependency> <!-- dbcp connection pool -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>${commons-dbcp.version}</version>
<scope>runtime</scope>
</dependency> <!-- PERSISTENCE end -->
<!-- WEB begin -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>jdom</groupId>
<artifactId>jdom</artifactId>
<version>${jdom.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>${javax.servlet.jstl.version}</version>
</dependency>
<dependency>
<groupId>net.sourceforge.jexcelapi</groupId>
<artifactId>jxl</artifactId>
<version>${jxl.version}</version>
</dependency> <dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>${javax.servlet.api.version}</version>
<scope>provided</scope>
</dependency>
<!-- JSR303 BeanValidator -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${hibernate-validator.version}</version>
</dependency>
<!-- pinyin4j begin -->
<!-- <dependency> <groupId>pinyin4j</groupId> <artifactId>pinyin4j</artifactId>
<version>${pinyin4j.version}</version> </dependency> -->
<!-- pinyin4j end -->
<!-- JSON begin -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>${jackson-asl.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>${jackson-asl.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
<version>${jackson-asl.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-xc</artifactId>
<version>${jackson-asl.version}</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>${gson.version}</version>
</dependency>
<dependency>
<groupId>quartz</groupId>
<artifactId>quartz</artifactId>
<version>${quartz.version}</version>
</dependency>
<!-- JSON end --> <!-- LOGGING begin -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
<scope>runtime</scope>
</dependency>
<!-- common-logging 实际调用slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
<scope>runtime</scope>
</dependency>
<!-- java.util.logging 实际调用slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${slf4j.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.lazyluke</groupId>
<artifactId>log4jdbc-remix</artifactId>
<version>0.2.7</version>
<scope>runtime</scope>
</dependency>
<!-- LOGGING end -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>org.kohsuke.stapler</groupId>
<artifactId>json-lib</artifactId>
<version>${org.kohsuke.stapler.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring-web.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-hibernate3</artifactId>
<version>${spring-hibernate3.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>${codec.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>${commons-collections.version}</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>${commons-fileupload.version}</version>
</dependency>
<!-- GENERAL UTILS end --> <!-- OTHER TOOLS begin -->
<!-- httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>${httpclient.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>${commons-httpclient.version}</version>
</dependency> <!-- template engine -->
<!-- <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId>
<version>${freemarker.version}</version> </dependency> --> <!-- third party dependencies -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>${dom4j.version}</version>
</dependency> <!-- email -->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>${javax.mail.version}</version>
</dependency>
<dependency>
<groupId>commons-email</groupId>
<artifactId>commons-email</artifactId>
<version>${commons-email.version}</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>${javax.activation.version}</version>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>${javax.transaction.version}</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>${velocity.version}</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>${c3p0.version}</version>
</dependency> <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency> <dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<!-- h2 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
<scope>test</scope>
</dependency> <dependency>
<groupId>antlr</groupId>
<artifactId>antlr</artifactId>
<version>${antlr.version}</version>
</dependency>
<dependency>
<groupId>net.sourceforge.jchardet</groupId>
<artifactId>jchardet</artifactId>
<version>${jchardet.version}</version>
</dependency>
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.4.01</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>3.1.4.RELEASE</version>
</dependency> <dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.9</version>
<exclusions>
<exclusion>
<artifactId>xml-apis</artifactId>
<groupId>xml-apis</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<finalName>springSecurity</finalName>
<plugins> <plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
<webAppConfig>
<contextPath>/springSecurity</contextPath>
</webAppConfig>
</configuration>
</plugin>
</plugins>
</build>
</project>

applicationContext-dao.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"
default-lazy-init="true"> <description>Spring DAO Configration</description> <!-- Spring Data Jpa配置 -->
<jpa:repositories base-package="com.wiker"
transaction-manager-ref="transactionManager"
entity-manager-factory-ref="entityManagerFactory" /> <bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!-- Connection Info -->
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://127.0.0.1:3306/test" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean> <!-- 利用Spring的实体管理器工厂来创建JPA实体管理器 -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan">
<list>
<value>com.wiker</value>
</list>
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="MYSQL" />
<property name="showSql" value="true" />
<property name="generateDdl" value="true" />
</bean>
</property>
</bean> <context:component-scan base-package="com.wiker"></context:component-scan> <context:annotation-config /> <!-- Jpa 事务配置 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean> <!-- 使用annotation定义事务 -->
<tx:annotation-driven transaction-manager="transactionManager"
proxy-target-class="true" /> </beans>

applicationContext-service.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"
default-lazy-init="true"> <description>Spring Service Configration</description> <!-- scan service class with @components -->
<context:component-scan base-package="com.wiker.security.service" /> <bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:application.properties</value>
</list>
</property>
</bean> <!-- <bean name="propertyLoader"
class="com.urbanmania.spring.beans.factory.config.annotations.PropertyFileLoader">
<property name="resources">
<value>classpath:application.properties</value>
</property>
</bean> <bean
class="com.urbanmania.spring.beans.factory.config.annotations.PropertyAnnotationAndPlaceholderConfigurer">
<property name="propertyLoaders">
<ref bean="propertyLoader" />
</property>
</bean> -->
</beans>

spring-security.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd"> <!-- 启用注解方式对方法的权限控制 -->
<security:global-method-security
pre-post-annotations="enabled" secured-annotations="enabled"
jsr250-annotations="enabled" proxy-target-class="true">
<!-- <security:protect-pointcut access="VIP"
expression="execution(* com.zf.service.VipService.*(..))" /> -->
</security:global-method-security> <!--use-expressions="true" 的意思是开启表达式 access-denied-page的意思是,当验证权限失败后会跳转到的页面 -->
<security:http use-expressions="true" access-denied-page="/powermiss.jsp" entry-point-ref="authenticationProcessingFilterEntryPoint">
<!-- 对登录页面,所有的用户都可以访问 -->
<security:intercept-url pattern="/login.jsp*"
access="permitAll" />
<security:intercept-url pattern="/index.jsp*"
access="permitAll" />
<!-- <security:intercept-url pattern="/vip.jsp*"
access="hasRole('VIP')" />
<security:intercept-url pattern="/admin.jsp*"
access="hasRole('ADMIN')" />
对所有的资源,都必须要有COMM权限 才可以访问
<security:intercept-url pattern="/*"
access="hasRole('COMM')" /> --> <!-- 使用自己的过滤器 -->
<!-- 下面的配置表示将自己的过滤器放在FORM_LOGIN_FILTER过滤链的最前面(可以这样来验证登录验证码) -->
<security:custom-filter
ref="validateCodeAuthenticationFilter" position="FORM_LOGIN_FILTER"
/> <!-- 配置登录页面为login.jsp ,登录成功默认跳转到index.jsp,登录失败返回login.jsp并携带参数error=true -->
<!-- <security:form-login login-page="/login.jsp" default-target-url="/index.jsp" authentication-failure-url="/login.jsp?error=true" /> --> <!-- 退出配置 -->
<security:logout invalidate-session="true"
logout-success-url="/login.jsp" logout-url="/auth/logout" /> </security:http> <bean id="authenticationProcessingFilterEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/login.jsp"></property>
</bean> <!-- 验证码过滤器 -->
<bean id="validateCodeAuthenticationFilter"
class="com.wiker.security.controller.VolidateAuthCodeUsernamePasswordAuthenticationFilter">
<property name="authenticationSuccessHandler"
ref="loginLogAuthenticationSuccessHandler"></property>
<property name="authenticationFailureHandler"
ref="simpleUrlAuthenticationFailureHandler"></property>
<property name="authenticationManager" ref="authenticationManager"></property>
</bean> <!-- 登录成功 -->
<bean id="loginLogAuthenticationSuccessHandler"
class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<property name="defaultTargetUrl" value="/index.jsp"></property>
</bean> <!-- 登录失败 -->
<bean id="simpleUrlAuthenticationFailureHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<property name="defaultFailureUrl" value="/login.jsp?error=true"></property>
</bean> <!-- 配置一个认证管理器 -->
<security:authentication-manager alias="authenticationManager">
<!-- 使用自定义的UserDetailService -->
<security:authentication-provider
user-service-ref="accountService">
<!-- 下面的内容就可注释掉了 -->
<!-- <security:user-service> -->
<!-- 这样的配置表示向系统中添加了一个用户 用户名和密码都为admin ,并且该用户拥有ROLE_USER角色(角色可以用逗号隔开) -->
<!-- <security:user name="admin" password="admin" authorities="ROLE_USER"/> -->
<!-- </security:user-service> -->
</security:authentication-provider>
</security:authentication-manager> </beans>

spring-mvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"> <!-- 自动扫描且只扫描@Controller -->
<context:component-scan base-package="com.wiker.security.controller"
use-default-filters="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan> <!-- Application Message Bundle -->
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="messages" />
</bean> <!-- Json返回 乱码处理 -->
<bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean
class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
<bean
class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
</list>
</property>
</bean>
<bean
class="org.springframework.http.converter.ResourceHttpMessageConverter" />
<bean
class="org.springframework.http.converter.xml.SourceHttpMessageConverter" />
<bean
class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter" />
<bean
class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter" />
</list>
</property>
</bean> <mvc:annotation-driven /> <!-- 将无法mapping到Controller的path交给default servlet handler处理 -->
<mvc:default-servlet-handler /> <!-- 定义JSP文件的位置 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/" />
<property name="suffix" value=".jsp" />
</bean> <!-- Configure the multipart resolver for uploading -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver" /> </beans>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<context-param>
<param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
<param-value>messages</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:/applicationContext-dao.xml,
classpath*:/applicationContext-service.xml,
classpath*:/spring-security.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <servlet>
<servlet-name>springServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>CaptchaServlet</servlet-name>
<servlet-class>
com.wiker.security.controller.CaptchaServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CaptchaServlet</servlet-name>
<url-pattern>/captchaServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>springServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping> <!-- spring security -->
<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> </web-app>

index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head> <body>
<h3>登录成功,欢迎您:<sec:authentication property="name" /></h3>
<a href="<%=basePath%>admin.jsp">进入管理员页面</a>
<a href="<%=basePath%>vip.jsp">进入会员页面</a>
<a href="<%=basePath%>auth/logout">注销</a>
</body>
</html>

index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":"
+ request.getServerPort() + path + "/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
<style type="text/css">
div.error {
width: 260px;
border: 2px solid red;
background-color: yellow;
text-align: center;
} div.hide {
display: none;
}
</style>
</head>
<body>
<div class="error ${param.error == true ? '' : 'hide'}">
登陆失败<br>
${sessionScope['SPRING_SECURITY_LAST_EXCEPTION'].message}
</div>
<h3>用户登录</h3>
<!-- from的action地址,以及用户名密码的name 。都是spring-security固定的。 -->
<form action="<%=basePath%>j_spring_security_check" method="post"> <p>
<label for="j_username">Username</label> <input id="j_username"
name="j_username" type="text" />
</p> <p>
<label for="j_password">Password</label> <input id="j_password"
name="j_password" type="password" />
</p>
<p>
<label for="j_password">验证码:</label> <input id="j_password"
name="code" type="password" /> <IMG style="CURSOR: pointer"
onclick="this.src='captchaServlet?t='+(new Date().getTime());"
alt="看不清楚?请点击刷新验证码!" align='absmiddle' src="captchaServlet"
height="18" width="55">
</p>
<p>
<input type="checkbox" name="_spring_security_remember_me">两周之内不必登陆
</p> <input type="submit" value="Login" /> </form> </body>
</html>

powermiss.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>"> <title>My JSP 'powermiss.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
--> </head> <body> <h1 style="color: red;">对不起,您无权访问该资源!</h1> </body>
</html>

VolidateAuthCodeUsernamePasswordAuthenticationFilter.java

package com.wiker.security.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; import org.apache.commons.lang.StringUtils;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.TextEscapeUtils; /**
* @author Wiker Yong Email:<a href="mailto:wikeryong@gmail.com">wikeryong@gmail.com</a>
* @date 2013-7-15 下午5:56:54
* @version 1.0-SNAPSHOT
*/
public class VolidateAuthCodeUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter{ private boolean postOnly = true;
private boolean allowEmptyValidateCode = false;
private String sessionvalidateCodeField = DEFAULT_SESSION_VALIDATE_CODE_FIELD;
private String validateCodeParameter = DEFAULT_VALIDATE_CODE_PARAMETER;
public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME";
// session中保存的验证码
public static final String DEFAULT_SESSION_VALIDATE_CODE_FIELD = "rand";
// 输入的验证码
public static final String DEFAULT_VALIDATE_CODE_PARAMETER = "code"; @Override
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
if (postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException(
"Authentication method not supported: "
+ request.getMethod());
} String username = obtainUsername(request);
String password = obtainPassword(request); if (username == null) {
username = "";
} if (password == null) {
password = "";
} username = username.trim(); UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
username, password); // Place the last username attempted into HttpSession for views
HttpSession session = request.getSession(false); if (session != null || getAllowSessionCreation()) {
request.getSession().setAttribute(
SPRING_SECURITY_LAST_USERNAME_KEY,
TextEscapeUtils.escapeEntities(username));
} // Allow subclasses to set the "details" property
setDetails(request, authRequest);
// check validate code
if (!isAllowEmptyValidateCode())
checkValidateCode(request);
// 根据用户和密码查询 return this.getAuthenticationManager().authenticate(authRequest);
} /**
*
* <li>比较session中的验证码和用户输入的验证码是否相等</li>
*
*/
protected void checkValidateCode(HttpServletRequest request) {
String sessionValidateCode = obtainSessionValidateCode(request);
String validateCodeParameter = obtainValidateCodeParameter(request);
if (StringUtils.isEmpty(validateCodeParameter)
|| !sessionValidateCode.equalsIgnoreCase(validateCodeParameter)) {
throw new AuthenticationServiceException("验证码错误!");
}
} private String obtainValidateCodeParameter(HttpServletRequest request) {
return request.getParameter(validateCodeParameter);
} protected String obtainSessionValidateCode(HttpServletRequest request) {
Object obj = request.getSession()
.getAttribute(sessionvalidateCodeField);
return null == obj ? "" : obj.toString();
} public boolean isPostOnly() {
return postOnly;
} @Override
public void setPostOnly(boolean postOnly) {
this.postOnly = postOnly;
} public String getValidateCodeName() {
return sessionvalidateCodeField;
} public void setValidateCodeName(String validateCodeName) {
this.sessionvalidateCodeField = validateCodeName;
} public boolean isAllowEmptyValidateCode() {
return allowEmptyValidateCode;
} public void setAllowEmptyValidateCode(boolean allowEmptyValidateCode) {
this.allowEmptyValidateCode = allowEmptyValidateCode;
} }

User.java

package com.wiker.security.dao.entity;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List; import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table; /**
* 用户Bean
* @author WikerYong <a>Email:yw_312@foxmail.com<a/>
* @version 2011-11-9 上午10:03:18
*/
@Entity
@Table(name = "user")
public class User implements Serializable{ protected static final long serialVersionUID = -5204668503508016656L; @Id
@GeneratedValue(strategy = GenerationType.AUTO)
protected Long id;
protected String username;
protected String password;
@ManyToMany
@JoinTable(name="user_role" , joinColumns = {
@JoinColumn(name = "userid")
}, inverseJoinColumns = {@JoinColumn(name="roleid")})
private List<Role> roles = new ArrayList<Role>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
}

UserDao.java

package com.wiker.security.dao.repository;

import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.PagingAndSortingRepository; import com.wiker.security.dao.entity.User; /**
* @author Wiker Yong Email:<a href="mailto:wikeryong@gmail.com">wikeryong@gmail.com</a>
* @date 2013-6-19 上午11:11:52
* @version 1.0-SNAPSHOT
*/
public interface UserDao extends PagingAndSortingRepository<User,Long>,JpaSpecificationExecutor<User> { User findByUsernameAndPassword(String username,String password); User findByUsername(String username); }

AccountService.java

package com.wiker.security.service;

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.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service; import com.wiker.security.dao.entity.User;
import com.wiker.security.dao.repository.UserDao; @Service
public class AccountService
implements UserDetailsService { @Autowired
private UserDao userDao; public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
User user = userDao.findByUsername(username);
UserDetails userDetail = null;
if (user != null) {
userDetail = new org.springframework.security.core.userdetails.User(username,
user.getPassword(), true, true, true, true, findUserAuthorities(user));
} return userDetail;
} /**
* 获取用户的权限
*
* @param user
* @return
*/
@SuppressWarnings("deprecation")
public Collection<GrantedAuthority> findUserAuthorities(User user) {
List<GrantedAuthority> autthorities = new ArrayList<GrantedAuthority>();
/*List<Role> roles = user.getRoles();
for (Role Role : roles) {
autthorities.add(new GrantedAuthorityImpl(Role.getRoleCode()));
}*/
autthorities.add(new GrantedAuthorityImpl("admin"));
return autthorities;
} }

Spring Security3实现,权限动态获取的更多相关文章

  1. JavaEE学习之Spring Security3.x——模拟数据库实现用户,权限,资源的管理

    一.引言 因项目需要最近研究了下Spring Security3.x,并模拟数据库实现用户,权限,资源的管理. 二.准备 1.了解一些Spring MVC相关知识: 2.了解一些AOP相关知识: 3. ...

  2. 动态获取Android权限

    @TargetApi(23)private void showPhotoDialog() { if (dialog != null && dialog.isShowing()) { d ...

  3. 使用Spring Security3的四种方法概述

    使用Spring Security3的四种方法概述 那么在Spring Security3的使用中,有4种方法: 一种是全部利用配置文件,将用户.权限.资源(url)硬编码在xml文件中,已经实现过, ...

  4. (39.2). Spring Boot Shiro权限管理【从零开始学Spring Boot】

    (本节提供源代码,在最下面可以下载) (4). 集成Shiro 进行用户授权 在看此小节前,您可能需要先看: http://412887952-qq-com.iteye.com/blog/229973 ...

  5. (39.1) Spring Boot Shiro权限管理【从零开始学Spring Boot】

    (本节提供源代码,在最下面可以下载)距上一个章节过了二个星期了,最近时间也是比较紧,一直没有时间可以写博客,今天难得有点时间,就说说Spring Boot如何集成Shiro吧.这个章节会比较复杂,牵涉 ...

  6. Spring中的JDK动态代理

    Spring中的JDK动态代理 在JDK1.3以后提供了动态代理的技术,允许开发者在运行期创建接口的代理实例.在Sun刚推出动态代理时,还很难想象它有多大的实际用途,现在动态代理是实现AOP的绝好底层 ...

  7. Spring Security3学习实例

    Spring Security是什么? Spring Security,这是一种基于Spring AOP和Servlet过滤器的安全框架.它提供全面的安全性解决方案,同时在Web请求级和方法调用级处理 ...

  8. Spring security3

    最近一直在学习spring security3,试着搭建了环境: 构建maven环境 项目配置pom.xml文件 <project xmlns="http://maven.apache ...

  9. Spring AOP中的动态代理

    0  前言 1  动态代理 1.1 JDK动态代理 1.2 CGLIB动态代理 1.2.1 CGLIB的代理用法 1.2.2 CGLIB的过滤功能 2  Spring AOP中的动态代理机制 2.1  ...

随机推荐

  1. KVM下windows虚拟机使用virtio驱动

    KVM下windows虚拟机默认disk使用的是Qemu IDE硬盘,网卡默认是rtl8139网卡.为了使kvm主机在相同的配置下,有更好的效率,可以将网卡和磁盘替换成virtio的驱动. windo ...

  2. proc中tran的一般处理

    存储过程事物的处理 一般情况在proc中判断的处理我们都采用 ) begin select '错误' return end 而在tran中我们最好用抛异常的方式 begin try begin SET ...

  3. Bullcow 牡牛和牝牛(bzoj 3398)

    Description     约翰要带N(1≤N≤100000)只牛去参加集会里的展示活动,这些牛可以是牡牛,也可以是牝牛.牛们要站成一排.但是牡牛是好斗的,为了避免牡牛闹出乱子,约翰决定任意两只牡 ...

  4. 【定位:PDF文件定位关键字所在坐标和页码】

    iText简介: iText是著名的开放源码的站点sourceforge一个项目,是用于生成PDF文档的一个java类库.通过iText不仅可以生成PDF或rtf的文档,而且可以将XML.Html文件 ...

  5. CSS3的翻转效果

    css3图片与文字3D transform切换: http://www.w3cplus.com/demo/419.html 详细的CSS3属性详解: http://www.zhangxinxu.com ...

  6. Stack Overflow for web end

    Jquery UI tooltip on disabled button In general, disabled elements do not trigger any DOM events. Th ...

  7. apache动态添加模块

    Apache已经安装完毕并投入运行,但是后来却发现部分模块没有加载,当然有两个方法: 1. 一是完全重新编译Apache, 再安装 2. 编译模块为SO文件,使用LoadModule指令加载扩展模块. ...

  8. WebSocket的原理,以及和Http的关系

    一.WebSocket是HTML5中的协议,支持持久连接:而Http协议不支持持久连接. 首先HTMl5指的是一系列新的API,或者说新规范,新技术.WebSocket是HTML5中新协议.新API. ...

  9. HDU 1017 A Mathematical Curiosity(枚举)

    题目链接 Problem Description Given two integers n and m, count the number of pairs of integers (a,b) suc ...

  10. Git 的 .gitignore 配置 转载

    .gitignore 配置文件用于配置不需要加入版本管理的文件,配置好该文件可以为我们的版本管理带来很大的便利,以下是个人对于配置 .gitignore 的一些心得. 1.配置语法: 以斜杠“/”开头 ...