spring security+mybatis+springMVC构建一个简单的项目

1.引用

spring security ,这是一种基于spring AOP和Servlet的过滤安全框架。它提供全面的安全性解决方案,同时在web请求级和方法的调用级处理身份确认和授权。在spring framework基础上,spring security充分利用了依赖注入(DI,Dependency Injection)和AOP技术。

下面就让我们用一个小的晓得项目来出初步了解Spring Security 的强大功能吧。

2.项目实战

   1)项目的技术架构:maven+spring security+springmvc+mybatis。

      当然后面还会有持久层采用hibernate框架的。话说得再多,还不如做一个项目来的实在,下面就让我们开始我们的项目吧。本项目涉及到的知识点可能比较多,对基础的要求比较高,请谨慎阅读。

  项目部分:

    1)项目结构图:

2)web.xml文件,它是所有web项目的入口文件,我们就从它开始下手吧。


<?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_3_0.xsd" id="WebApp_ID" version="3.0">

  <display-name>mybatis</display-name>

  

  <context-param>

    <param-name>contextConfigLocation</param-name>

    <param-value>classpath:spring.xml,classpath:spring-mybatis.xml,classpath:spring-security.xml</param-value>

  </context-param>

  

  <servlet>

    <description>spring mvc servlet</description>

    <servlet-name>springMvc</servlet-name>

    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

    <init-param>

      <description>spring mvc 配置文件</description>

      <param-name>contextConfigLocation</param-name>

      <param-value>classpath:spring-mvc.xml</param-value>

    </init-param>

    <load-on-startup>1</load-on-startup>

  </servlet>

  <servlet-mapping>

    <servlet-name>springMvc</servlet-name>

    <url-pattern>/</url-pattern>

  </servlet-mapping>

  

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

  

  <filter>

    <description>字符集过滤器</description>

    <filter-name>encodingFilter</filter-name>

    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

    <init-param>

      <description>字符集编码</description>

      <param-name>encoding</param-name>

      <param-value>UTF-8</param-value>

    </init-param>

  </filter>

  <filter-mapping>

    <filter-name>encodingFilter</filter-name>

    <url-pattern>/*</url-pattern>

  </filter-mapping>

  <!-- 配置session监听器 -->

  <listener>

      <description>session监听器</description>

      <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>

  </listener>

  

  <listener>

    <description>spring监听器</description>

    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

  </listener>

  <listener>

    <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>

  </listener>

  

      <context-param>  

        <param-name>spring.profiles.active</param-name>  

        <param-value>dev</param-value>  

    </context-param>  

    <context-param>  

        <param-name>spring.profiles.default</param-name>  

        <param-value>dev</param-value>  

    </context-param>  

    <context-param>  

        <param-name>spring.liveBeansView.mbeanDomain</param-name>  

        <param-value>dev</param-value>  

    </context-param>  

  

  <welcome-file-list>

    <welcome-file>/index.jsp</welcome-file>

  </welcome-file-list>

  <session-config>

    <session-timeout>15</session-timeout>

  </session-config>

</web-app>

   3).我们的项目要尽量的贴合实际项目,所以项目中我也整合了数据库,因为大部分应用中mysql用得比较多,我就用mysql做吧


drop table if exists sec_user;

 

create table sec_user(

    id int(11) primary key auto_increment,

    username varchar(50),

    password varchar(50),

    role     varchar(50),

    access   int(10)

    )enging=inno_db default charset=utf8;

4 ).实际项目中会采用maven进行jar包的管理,此项目我们也采用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>mybatis_security_session</groupId>

	<artifactId>mybatis_security_session</artifactId>

	<packaging>war</packaging>

	<version>0.0.1-SNAPSHOT</version>

	<name>springsecurity Maven Webapp</name>

	<url>http://maven.apache.org</url>

	<dependencies>

		<dependency>

			<groupId>org.springframework</groupId>

			<artifactId>spring-test</artifactId>

			<version>3.2.0.RELEASE</version>

		</dependency>

		<dependency>

			<groupId>org.springframework</groupId>

			<artifactId>spring-webmvc</artifactId>

			<version>3.2.0.RELEASE</version>

		</dependency>

		<dependency>

			<groupId>org.springframework</groupId>

			<artifactId>spring-core</artifactId>

			<version>3.2.0.RELEASE</version>

		</dependency>

		<dependency>

           <groupId>org.springframework.security</groupId>

           <artifactId>spring-security-config</artifactId>

           <version>3.2.0.RELEASE</version>

         </dependency>

         <dependency>

             <groupId>org.springframework.security</groupId>

             <artifactId>spring-security-taglibs</artifactId>

             <version>3.2.0.RELEASE</version>

        </dependency>

		<dependency>

			<groupId>org.mybatis</groupId>

			<artifactId>mybatis</artifactId>

			<version>3.1.1</version>

		</dependency>

		<dependency>

			<groupId>org.mybatis</groupId>

			<artifactId>mybatis-spring</artifactId>

			<version>1.2.2</version>

		</dependency>

		<dependency>

            <groupId>javax.annotation</groupId>

            <artifactId>javax.annotation-api</artifactId>

            <version>1.2</version>

        </dependency>

		<dependency>

			<groupId>mysql</groupId>

			<artifactId>mysql-connector-java</artifactId>

			<version>5.1.21</version>

		</dependency>

		<dependency>

           <groupId>org.apache.struts</groupId>

           <artifactId>struts2-dojo-plugin</artifactId>

           <version>2.3.24.1</version>

        </dependency>

		<dependency>

			<groupId>junit</groupId>

			<artifactId>junit</artifactId>

			<version>4.11</version>

			<scope>test</scope>

		</dependency>

		<dependency>

			<groupId>org.aspectj</groupId>

			<artifactId>aspectjweaver</artifactId>

			<version>1.7.1</version>

		</dependency>

		<dependency>

			<groupId>org.codehaus.jackson</groupId>

			<artifactId>jackson-mapper-asl</artifactId>

			<version>1.9.11</version>

		</dependency>

		<dependency>

			<groupId>commons-fileupload</groupId>

			<artifactId>commons-fileupload</artifactId>

			<version>1.2.2</version>

		</dependency>

		<dependency>

			<groupId>javax.servlet</groupId>

			<artifactId>servlet-api</artifactId>

			<version>3.0-alpha-1</version>

		</dependency>

		<dependency>

			<groupId>javax.servlet</groupId>

			<artifactId>jstl</artifactId>

			<version>1.2</version>

		</dependency>

		<dependency>

			<groupId>log4j</groupId>

			<artifactId>log4j</artifactId>

			<version>1.2.17</version>

		</dependency>

		<!--alibaba 数据源jar 来刮泥数据源  -->

		<dependency>

			<groupId>com.alibaba</groupId>

			<artifactId>druid</artifactId>

			<version>0.2.9</version>

		</dependency>

		<dependency>

			<groupId>com.alibaba</groupId>

			<artifactId>fastjson</artifactId>

			<version>1.1.26</version>

		</dependency>

	</dependencies>

	<build>

	</build>

</project>

5)实体部分

a.实体类文件  user.java


package sy.model;




import java.io.Serializable;

 

public class User implements  Serializable{

    

	private static final long serialVersionUID = 1L;

 

	private Integer id;

 

    private String username;

 

    private String password;

 

    private String role;

    

    private int access;

 

    public int getAccess() {

		return access;

	}

 

	public void setAccess(int access) {

		this.access = access;

	}

 

	public Integer getId() {

        return id;

    }

 

    public void setId(Integer id) {

        this.id = id;

    }

 

    public String getUsername() {

        return username;

    }

 

    public void setUsername(String username) {

        this.username = username == null ? null : username.trim();

    }

 

    public String getPassword() {

        return password;

    }

 

    public void setPassword(String password) {

        this.password = password == null ? null : password.trim();

    }

 

    public String getRole() {

        return role;

    }

 

    public void setRole(String role) {

        this.role = role == null ? null : role.trim();

    }

 

}

b.user的映射文件,写得比较简单。

UserMapper.xml文件


<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >

<mapper namespace="sy.dao.UserMapper" >

  <resultMap id="BaseResultMap" type="sy.model.User" >

    <id column="id" property="id" jdbcType="INTEGER" />

    <result column="username" property="username" jdbcType="VARCHAR" />

    <result column="password" property="password" jdbcType="VARCHAR" />

    <result column="role" property="role" jdbcType="VARCHAR" />

    <result column="access" property="access" jdbcType="INTEGER" />


  </resultMap>

  <sql id="Base_Column_List" >

    id, username, password, role,access

  </sql>

  <select id="selectByUserName" resultMap="BaseResultMap" parameterType="java.lang.Integer" >

    select 

    <include refid="Base_Column_List" />

    from sec_user

    where username = #{username,jdbcType=VARCHAR}

  </select>

  

  <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer">

     select

     <include refid="Base_Column_List"/>

       from sec_user

       where id = #{id,jdbcType=INTEGER}

  </select>

</mapper>

6)dao层,业务数据处理层。因为采用的是mybatis框架,所以dao层会特别的简单,这也侧面的体现了mybatis的强大。

UserMaper.java文件


package sy.dao;

 

import sy.model.User;

 

public interface UserMapper {

   

    User selectByUserName(String username);

 

    User selectByPrimaryKey(Integer id);

   

}

7)要写配置文件了,这是个比较重要的部分,当然也特别的基础。以下会有多个配置文件,而且没有配置文件功能都细分的的很明确。

a ,   config.properties文件:存放数据库连接时必须用到的信息


#hibernate.dialect=org.hibernate.dialect.OracleDialect

#driverClassName=oracle.jdbc.driver.OracleDriver

#validationQuery=SELECT 1 FROM DUAL

#jdbc_url=jdbc:oracle:thin:@localhost:1521:orcl

#jdbc_username=sypro

#jdbc_password=sypro

 

hibernate.dialect=org.hibernate.dialect.MySQLDialect

driverClassName=com.mysql.jdbc.Driver

validationQuery=SELECT 1

jdbc_url=jdbc:mysql://localhost:3306/sy?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true          

jdbc_username=root

jdbc_password=1234

 

#hibernate.dialect=org.hibernate.dialect.SQLServerDialect

#driverClassName=net.sourceforge.jtds.jdbc.Driver

#validationQuery=SELECT 1

#jdbc_url=jdbc:jtds:sqlserver://127.0.0.1:1433/sy

#jdbc_username=sa

#jdbc_password=123456

 

#hibernate.dialect=org.hibernate.dialect.DerbyDialect

#driverClassName=org.apache.derby.jdbc.EmbeddedDriver

#validationQuery=SELECT 1

#jdbc_url=jdbc:derby:sy;create=true

#jdbc_username=sypro

#jdbc_password=sypro

 

#jndiName=java:comp/env/dataSourceName

 

#hibernate.hbm2ddl.auto=update

#hibernate.show_sql=false

#hibernate.format_sql=true

 

sessionInfoName=sessionInfo

 

uploadFieldName=filedata

uploadFileMaxSize=20971520

uploadFileExts=txt,rar,zip,doc,docx,xls,xlsx,jpg,jpeg,gif,png,swf,wmv,avi,wma,mp3,mid

uploadDirectory=attached

b,log4j文件配置,里面的信息不做详细说明。

log4j.properties文件


log4j.rootLogger=DEBUG,Console,File

 

log4j.appender.Console=org.apache.log4j.ConsoleAppender

log4j.appender.Console.Target=System.out

log4j.appender.Console.layout=org.apache.log4j.PatternLayout

log4j.appender.Console.layout.ConversionPattern=[%c]%m%n

 

log4j.appender.File=org.apache.log4j.RollingFileAppender 

log4j.appender.File.File=mybatis.log

log4j.appender.File.MaxFileSize=10MB

log4j.appender.File.Threshold=ALL

log4j.appender.File.layout=org.apache.log4j.PatternLayout

log4j.appender.File.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH\:mm\:ss,SSS}][%c]%m%n

c,以下的配置文件会比较重要。

spring.xml文件,存放通用的逻辑  :获取配置文件比如像properties类的文件

扫面项目的包

开启各个注解功能


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

	xsi:schemaLocation="

http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-3.0.xsd

">

 

	<!-- 引入属性文件 -->

	<context:property-placeholder location="classpath:config.properties" />

 

	<!-- 自动扫描(自动注入) -->

	<context:component-scan base-package="sy" />

 

	<context:annotation-config />

		

	<!--jass config  -->

	<bean id="jaasAuthenticationProvider"

		class="org.springframework.security.authentication.jaas.JaasAuthenticationProvider">

		<property name="loginConfig" value="/WEB-INF/login.conf" />

		<property name="loginContextName" value="JAASTest" />

		<property name="callbackHandlers">

			<list>

				<bean

					class="org.springframework.security.authentication.jaas.JaasNameCallbackHandler" />

				<bean

					class="org.springframework.security.authentication.jaas.JaasPasswordCallbackHandler" />

			</list>

		</property>

		<property name="authorityGranters">

			<list>

				<bean

					class="sy.service.AuthorityGranterImpl" />

			</list>

		</property>

	</bean>

</beans>

d, mybatis的配置文件

spring-mybatis.xml文件。此部分配置了与数据源有关的东西:sessionFactory

spring事务控制AOP

采用的阿里巴巴的数据源jar包作业。


<?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:tx="http://www.springframework.org/schema/tx" 

 xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="

http://www.springframework.org/schema/beans 

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 

http://www.springframework.org/schema/tx 

http://www.springframework.org/schema/tx/spring-tx-3.0.xsd

http://www.springframework.org/schema/aop 

http://www.springframework.org/schema/aop/spring-aop-3.0.xsd

">

 

	<!-- JNDI方式配置数据源 -->

	<!-- <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="${jndiName}"></property> </bean> -->

 

	<!-- 配置数据源 -->

	<bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">

		

		 <!--数据源驱动类可以不用写,Druid默认会自动根据URL识别DriverClass  -->

       <!--  <property name="driverClassName" value="com.mysql.jdbc.Driver"/> -->

		<property name="url" value="${jdbc_url}" />

		<property name="username" value="${jdbc_username}" />

		<property name="password" value="${jdbc_password}" />

       

		<!-- 初始化连接大小 -->

		<property name="initialSize" value="0" />

		<!-- 连接池最大使用连接数量 -->

		<property name="maxActive" value="20" />

		<!-- 连接池最大空闲 -->

		<property name="maxIdle" value="20" />

		<!-- 连接池最小空闲 -->

		<property name="minIdle" value="0" />

		<!-- 获取连接最大等待时间 -->

		<property name="maxWait" value="60000" />

 

		<!-- <property name="poolPreparedStatements" value="true" /> <property name="maxPoolPreparedStatementPerConnectionSize" value="33" /> -->

 

		<property name="validationQuery" value="${validationQuery}" />

		<property name="testOnBorrow" value="false" />

		<property name="testOnReturn" value="false" />

		<property name="testWhileIdle" value="true" />

 

		<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->

		<property name="timeBetweenEvictionRunsMillis" value="60000" />

		<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->

		<property name="minEvictableIdleTimeMillis" value="25200000" />

 

		<!-- 打开removeAbandoned功能 -->

		<property name="removeAbandoned" value="true" />

		<!-- 1800秒,也就是30分钟 -->

		<property name="removeAbandonedTimeout" value="1800" />

		<!-- 关闭abanded连接时输出错误日志 -->

		<property name="logAbandoned" value="true" />

 

		<!--配置监控统计拦截  监控数据库 -->

		<!-- <property name="filters" value="stat" /> -->

		<property name="filters" value="mergeStat" />

	</bean>

 

	<!--  配置SqlsessionFactoryBean myBatis文件-->

	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

		<property name="dataSource" ref="dataSource" />

		<!-- 自动扫描entity目录, 省掉Configuration.xml里的手工配置 -->

		<property name="mapperLocations" value="classpath:sy/mapping/*.xml" />

	</bean>

 

	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

		<property name="basePackage" value="sy.dao" />

		<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />

	</bean>

 

	<!-- 配置事务管理器 -->

	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

		<property name="dataSource" ref="dataSource" />

	</bean>

 

	<!-- 注解方式配置事物 -->

	<!-- <tx:annotation-driven transaction-manager="transactionManager" /> -->

 

	<!-- 拦截器方式配置事物 -->

	<tx:advice id="transactionAdvice" transaction-manager="transactionManager">

		<tx:attributes>

			<tx:method name="add*" propagation="REQUIRED" />

			<tx:method name="append*" propagation="REQUIRED" />

			<tx:method name="insert*" propagation="REQUIRED" />

			<tx:method name="save*" propagation="REQUIRED" />

			<tx:method name="update*" propagation="REQUIRED" />

			<tx:method name="modify*" propagation="REQUIRED" />

			<tx:method name="edit*" propagation="REQUIRED" />

			<tx:method name="delete*" propagation="REQUIRED" />

			<tx:method name="remove*" propagation="REQUIRED" />

			<tx:method name="repair" propagation="REQUIRED" />

			<tx:method name="delAndRepair" propagation="REQUIRED" />

 

			<tx:method name="get*" propagation="SUPPORTS" />

			<tx:method name="find*" propagation="SUPPORTS" />

			<tx:method name="load*" propagation="SUPPORTS" />

			<tx:method name="search*" propagation="SUPPORTS" />

			<tx:method name="datagrid*" propagation="SUPPORTS" />

 

			<tx:method name="*" propagation="SUPPORTS" />

		</tx:attributes>

	</tx:advice>

	

	<aop:config>

		<aop:pointcut id="transactionPointcut" expression="execution(* sy.service..*Impl.*(..))" />

		<aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice" />

	</aop:config>

 

 

	<!-- 配置druid监控spring jdbc -->

	<bean id="druid-stat-interceptor" class="com.alibaba.druid.support.spring.stat.DruidStatInterceptor">

	</bean>

	<bean id="druid-stat-pointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut" scope="prototype">

		<property name="patterns">

			<list>

				<value>sy.service.*</value>

			</list>

		</property>

	</bean>

	<aop:config>

		<aop:advisor advice-ref="druid-stat-interceptor" pointcut-ref="druid-stat-pointcut" />

	</aop:config>

 

</beans>

e,我们比较熟悉的部分了springMVC的配置文件,说是控制层的配置文件也是很有道理的

spring-mvc.xml文件


<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans 

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 

http://www.springframework.org/schema/context 

http://www.springframework.org/schema/context/spring-context-3.0.xsd 

http://www.springframework.org/schema/mvc 

http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

 

	<!-- 自动扫描controller包下的所有类,使其认为spring mvc的控制器 -->

	<context:component-scan base-package="sy.controller" />

 

	<!-- 避免IE执行AJAX时,返回JSON出现下载文件 -->

	<bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">

		<property name="supportedMediaTypes">

			<list>

				<value>text/html;charset=UTF-8</value>

			</list>

		</property>

	</bean>

 

	<!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射 -->

	<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">

		<property name="messageConverters">

			<list>

				<ref bean="mappingJacksonHttpMessageConverter" /><!-- json转换器 -->

			</list>

		</property>

	</bean>

 

	<!-- 对模型视图名称的解析,即在模型视图名称添加前后缀 -->

	<bean id="viewResolver"  class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/views/" p:suffix=".jsp" />

	

	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

		<property name="defaultEncoding">

			<value>UTF-8</value>

		</property>

		<property name="maxUploadSize">

			<value>32505856</value><!-- 上传文件大小限制为31M,31*1024*1024 -->

		</property>

		<property name="maxInMemorySize">

			<value>4096</value>

		</property>

	</bean>

 

</beans>

f,这文件应该是我们最关注的spring-security.xml文件,这文件可能没有多少注解,我希望大家能去网上多看看文档,这样记忆文比较深刻,我写出来没有多少意义,因为这个文件是spring security的关键。


<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-3.2.xsd">

 

 

	<http auto-config="true" use-expressions="true"

		access-denied-page="/auth/denied"> <!-- 拒绝被方访问时转向改页面 -->

 

 

		<intercept-url pattern="/auth/login" access="permitAll" />

		<intercept-url pattern="/main/admin" access="hasRole(‘ROLE_ADMIN‘)" />

		<intercept-url pattern="/main/common" access="hasRole(‘ROLE_USER‘)" />

 

		<form-login login-page="/auth/login"

			authentication-failure-url="/auth/login?error=true"

			default-target-url="/main/common" />

		<logout invalidate-session="true" logout-success-url="/auth/login"

			logout-url="/auth/logout" />

 

		<session-management>

			<concurrency-control max-sessions="1"

				error-if-maximum-exceeded="true" expired-url= "/auth/login?error=expired" />

		</session-management>

 

      <!--退出登录是删除对应的session 信息  -->

      <logout delete-cookies="JSESSIONID"/>

 

		<http-basic />

 

	</http>

<!-- 方法级别的权限控制,需要用这个注解标签来开启--> 

	<global-method-security jsr250-annotations="enabled" />

 

	<authentication-manager>

	<!--这里必须用ref来连接   不能用user-service-ref 来连接     ,它是用来连接userDetailsService接口的实现的  -->

		<authentication-provider ref="jaasAuthenticationProvider" />

	</authentication-manager>

 

</beans:beans>  

好了到此配置文件就完成了,下面将是项目的核心部分了,当然spring security也在里面,jsp文件我将贴在最后面

核心代码块:

控制层(controller):

LoginLoginoutController.java文件


package sy.controller;




import org.apache.log4j.Logger;  

import org.springframework.stereotype.Controller;  

import org.springframework.ui.ModelMap;  

import org.springframework.web.bind.annotation.RequestMapping;  

import org.springframework.web.bind.annotation.RequestMethod;  

import org.springframework.web.bind.annotation.RequestParam;  

  

@Controller  

@RequestMapping("auth")  

public class LoginLogoutController {  

  

    protected static Logger logger = Logger.getLogger("controller");  

  

    /** 

     * 指向登录页面 

     */  

    @RequestMapping(value = "/login", method = RequestMethod.GET)  

    public String getLoginPage(  

            @RequestParam(value = "error", required = false) boolean error,  

            ModelMap model) {  

  

        logger.debug("Received request to show login page");  

  

        if (error == true) {  

            // Assign an error message  

            model.put("error",  

                    "You have entered an invalid username or password!");  

        } else {  

            model.put("error", "");  

        }  

        return "loginpage";  

  

    }  

  

    /** 

     * 指定无访问额权限页面 

     *  

     * @return 

     */  

    @RequestMapping(value = "/denied", method = RequestMethod.GET)  

    public String getDeniedPage() {  

  

        logger.debug("Received request to show denied page");  

  

        return "deniedpage";  

  

    }  

}  

MainController.java文件


package sy.controller;

import org.apache.log4j.Logger;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;  

import org.springframework.web.bind.annotation.RequestMapping;  

import org.springframework.web.bind.annotation.RequestMethod;

 

import sy.model.User;

import sy.service.UserServiceI;  

  

@Controller  

@RequestMapping("/main")  

public class MainController {  

    protected static Logger logger = Logger.getLogger("controller");  

  

    private UserServiceI sevice;

    

    @Autowired

    public void setSevice(UserServiceI sevice) {

		this.sevice = sevice;

	}

 

	/** 

     * 跳转到commonpage页面 

     *  

     * @return 

     */  

    @RequestMapping(value = "/common", method = RequestMethod.GET)  

    public String getCommonPage() {  

  //这里是为spring security在方法级别的控制而准备的,getUserByPrimary方法,需要RELE_ADMIN权限

    	User user = sevice.getUserByPrimaryKey(1);

    	System.err.println("---------"+user.getUsername());

        logger.debug("Received request to show common page");  

        return "commonpage";  

    }  

  

    /** 

     * 跳转到adminpage页面 

     *  

     * @return 

     */  

    @RequestMapping(value = "/admin", method = RequestMethod.GET)  

    public String getAadminPage() {  

        logger.debug("Received request to show admin page");  

        return "adminpage";  

  

    }  

  

}  

UserDetails接口的实现,这个接口是为UserDetailsService服务的,当然我们做的这个项目使用jaas认证来写,这个类用不到,提到了就给大家贴出来。

JAAS的定义:Java Authentication Service(JAAS,Java验证和授权)提供灵活可伸缩的的机制来保护客户端或服务器端的java程序。JAAS强调的是通过验证谁在运行代码以及他/她的权限来保护系统免受用户的攻击。它让你能够将一些标准的安全机制,列如Solaris,NIS(网络信息服务),Windsow NT,LDAP(轻量目录存取协议),Kerberos等通过一种通用的,可以配置的方式集成到系统中去。

UserLoginDetails.java文件


package sy.security;

 

import java.util.Collection;

 

import org.springframework.security.core.GrantedAuthority;

import org.springframework.security.core.userdetails.UserDetails;

 

public class UserLoginDetails implements UserDetails{

 

 

	private static final long serialVersionUID = 1L;

	private String username;

	private String password;

	private boolean enabled;

	private Collection<? extends GrantedAuthority> authorities;

	

	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 void setEnabled(boolean enabled) {

		this.enabled = enabled;

	}

 

	public Collection<? extends GrantedAuthority> getAuthorities() {

		return authorities;

	}

 

 

	public void setAuthorities(Collection<? extends GrantedAuthority> authorities) {

		this.authorities = authorities;

	}

 

	public boolean isAccountNonExpired() {

		return enabled;

	}

 

	public boolean isAccountNonLocked() {

		return enabled;

	}

 

	public boolean isCredentialsNonExpired() {

		return enabled;

	}

 

	public boolean isEnabled() {

		return enabled;

	}

 

}

sevice层,数据业务核心层

UserServiceI.java文件,这里我们又可以感受一下mybatis的强大了,是不是太简单了


package sy.service;

 

 

import sy.model.User;

import javax.annotation.security.RolesAllowed;

public interface UserServiceI {

 

	

    User getUserByUserName(String username);

 

    //spring security方法级别的控制,使用该方法需要的权限 

    @RolesAllowed("ROLE_ADMIN")

	User getUserByPrimaryKey(Integer id);

}

UserServiceImpl.java


package sy.service;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

 

import sy.dao.UserMapper;

import sy.model.User;

 

@Service("userService")

public class UserServiceImpl implements UserServiceI {

 

	private UserMapper userMapper;

 

	public UserMapper getUserMapper() {

		return userMapper;

	}

 

	@Autowired

	public void setUserMapper(UserMapper userMapper) {

		this.userMapper = userMapper;

	}

 

	public User getUserByUserName(String username) {

		

		System.err.println("find by name !");

		return userMapper.selectByUserName(username);

	}

 

	public User getUserByPrimaryKey(Integer id) {

		return userMapper.selectByPrimaryKey(id);

	}

 

	

 

}

Jaas核心代码块;

jass必须实现这两接口

AuthorityGranter  做权限的赋予

LoginModule  做登录的验证

AuthorityGranter接口的实现类 AuthorityGranterImpl.java


package sy.service;

 

import java.security.Principal;

import java.util.Set;

import javax.annotation.Resource;

import java.util.HashSet;

import org.springframework.security.authentication.jaas.AuthorityGranter;

import sy.model.User;

 

public class AuthorityGranterImpl implements AuthorityGranter{

 

	@Resource

	private UserServiceI serviceI;

	

	public Set<String> grant(Principal principal) {

		String name =  principal.getName();

		System.err.println("DefaultAuthorutyGranter Principal : "+name);

		

		User user = serviceI.getUserByUserName(name);

		

		String [] roles = user.getRole().split(",");

		Set<String> authoritys = new HashSet<String>();

		for(String role:roles){

			authoritys.add(role);			

		}

		

		//return Collections.singleton("ROLE_USER");

		return authoritys;

	}

 

}

LoginModule接口的实现类LoginModuleImpl.java


package sy.service;

 

import java.io.IOException;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.util.Map;

 

import javax.security.auth.Subject;

import javax.security.auth.callback.Callback;

import javax.security.auth.callback.CallbackHandler;

import javax.security.auth.callback.NameCallback;

import javax.security.auth.callback.PasswordCallback;

import javax.security.auth.callback.UnsupportedCallbackException;

import javax.security.auth.login.LoginException;

import javax.security.auth.spi.LoginModule;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;

 

public class LoginModuleImpl  implements LoginModule {

 

	private Subject subject;

	private CallbackHandler callbackHandler;

	private String username;

	private String password;

	private Map sharedState;

	private Map options;

 

	private String url;

	private String driver;

	private String db_username;

	private String db_password;

 

	public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,

			Map<String, ?> options) {

		this.subject = subject;

		this.callbackHandler = callbackHandler;

		this.sharedState = sharedState;

		this.options = options;

 

		url = (String) options.get("url");

		driver = (String) options.get("driver");

		db_username = (String) options.get("db_username");

		db_password = (String) options.get("db_password");

 

		/**

		 * 页面上的username 和password 由NameCallBack 和PasswordCallBack两个去获取

		 * 有callbackHandler去回调,然后再把他们获取出来

		 */

		try {

			//TextInputCallback textInputCallback = new TextInputCallback("prompt");

			NameCallback nameCallback = new NameCallback("prompt");

			PasswordCallback passwordCallback = new PasswordCallback("prompt", false);

			callbackHandler.handle(new Callback[] { nameCallback, passwordCallback });

 

			username = nameCallback.getName();

			password = new String(passwordCallback.getPassword());

 

		} catch (IOException e) {

			e.printStackTrace();

		} catch (UnsupportedCallbackException e) {

			e.printStackTrace();

		}

 

	}

 

	public boolean login() throws LoginException {

		// 1.Query and compare

		// 2.用户名和密码对比正确 返回true,错误返回false

		System.out.println("driver " + driver);

		System.out.println("url " + url);

		System.out.println("db_username " + db_username);

		System.out.println("db_password " + db_password);

 

		System.out.println("user " + username);

		System.out.println("password " + password);

 

		String dpwd = "";

		// String dtype = "";

 

		boolean flag = false;

 

		// 校验用户

		/*String sql = "select tp.name, tps.secretcode, tc.type from tperson tp "

				+ "inner join tcorp tc on tp.corpid = tc.objid "

				+ "inner join tpersonpsw tps on tp.objid = tps.objid where tp.name = ?";*/

 

		String sql = "select * from sec_user where username = ?";

		// 1.注册驱动

		// 2.获得连接

		Connection conn = null;

		PreparedStatement ps = null;

		ResultSet rs = null;

		try {

			Class.forName(driver);

			conn = DriverManager.getConnection(url, db_username, db_password);

			// 3.创建statement

			ps = conn.prepareStatement(sql);

			ps.setString(1, username);

			// 4.执行sql语句返回结果

			rs = ps.executeQuery();

 

			while (rs != null && rs.next()) {

				dpwd = rs.getString("password");

				flag = true;

			}

		} catch (SQLException e) {

			e.printStackTrace();

		} catch (ClassNotFoundException e) {

			e.printStackTrace();

		} finally {

			try {

				if (conn != null) {

					conn.close();

				}

				if (ps != null) {

					ps.close();

				}

				if (rs != null) {

					rs.close();

				}

			} catch (SQLException e) {

				e.printStackTrace();

			}

		}

		

		if(flag == false){throw new LoginException("User is not exist !");

		}

 

		if (dpwd.equals(password)) {

			UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username,

					password);

			subject.getPrincipals().add(authenticationToken);

			return true;

		} else {

			throw new LoginException("Username is not match the password ! ");

		}

	}

	

	public boolean commit() throws LoginException {

		return true;

	}

 

	public boolean abort() throws LoginException {

		return true;

	}

 

	public boolean logout() throws LoginException {

		return true;

	}

 

}

jass中要的配置文件:WEB-INF/login.conf


JAASTest {

    sy.service.LoginModuleImpl required

    driver="com.mysql.jdbc.Driver"  

    url="jdbc:mysql://localhost:3306/sy"  

    db_username="root"  

    db_password="1234"  

    debug="true";  

};

这个文件有spring.xml文件中jaas文件读取。需要注意的是LoginModule这个接口的实现,是不能纳入到spring容器中去的,它是由jaas的标准API加载,所以这里的需要加入数据库的连接数据,供loginModul的实现类从数据去数据。

以下是jsp文件

logingpage.jsp


    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>  

    <%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>  

    <%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>  

      

    <%@ 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">  

    <html>  

    <head>  

    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  

    <title>Insert title here</title>  

    </head>  

    <body>  

      

        <h1>Login</h1>  

      

        <div id="login-error">${error}</div>  

      

        <form action="../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>  

      

            <input type="submit" value="Login" />  

      

        </form>  

      

    </body>  

    </html>  

deniedpage.jsp文件


    <%@ 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">  

    <html>  

    <head>  

    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  

    <title>Insert title here</title>  

    </head>  

    <body>  

        <h1>你的权限不够!</h1>  

        <p>只有拥有Admin权限才能访问!</p>  

        <a href="/mybatis_security_session/auth/login">退出登录</a>  

    </body>  

    </html>  

commonpage.jsp文件


    <%@ 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">  

    <html>  

    <head>  

    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  

    <title>Insert title here</title>  

    </head>  

    <body>  

        <h1>Common Page</h1>  

        <p>每个人都能访问的页面.</p>  

        <a href="/mybatis_security_session/main/admin"> Go AdminPage </a>  

        <br />  

        <a href="/mybatis_security_session/auth/login">退出登录</a>  

      

    </body>  

    </html>  

adminpage.jsp文件


    <%@ 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">  

    <html>  

    <head>  

    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  

    <title>Insert title here</title>  

    </head>  

    <body>  

        <h1>Admin Page</h1>  

        <p>管理员页面</p>  

        <a href="/mybatis_security_session/auth/login">退出登录</a>  

    </body>  

    </html>  

项目我也上传了  ,若是需要可以搜索spring security+mybatis+springMVC 关键字 寻找资源

时间: 2024-10-14 10:29:05

spring security+mybatis+springMVC构建一个简单的项目的相关文章

基于Maven + SSM (Spring、SpringMVC、Mybatis)构建一个简单的测试项目

最近在公司实习期间的培训交流中有机会接触到SSM,然后自己花费1周的时间投入学习.谈不上深刻理解其中原理,所以没有涉及理论知识,只是浅层次的学习如何使用,在此将学习过程记录整理出来,一方面自己备用:另一方面,分享出来和做技术的各位讨论交流. 现阶段的我还做不到知行合一,所以决定先学会用,然后再去深究原理.若有不足以及错误之处,望多多包涵.指教,谢谢. 废话不多说,直接开干! 1.开发环境搭建 推荐博客地址: MyEclipse+Tomcat+MAVEN+SVN项目完整环境搭建 2.Maven W

LINUX下用Nginx和Node.js构建一个简单的项目(1)

由于我之前租了一个阿里云服务器,最近又开始学学Node.js,因此准备写点东西把过程记录一下.至于服务器上的Web环境安装阿里云有十分详细的安装说明,这里就略过了... 以下是我的Web环境: 服务器系统为LINUX 64位 Web:nginx Nginx:1.4.4 Php:5.3.29 Mysql:5.1.73 1.安装Nodejs 首先需要查看系统的Python和Make版本信息是否符合Node.js的安装环境.指令如下: # python # make -v 在官网下载nodejs(ht

LINUX下用Nginx和Node.js构建一个简单的项目(4)

发现了一个问题,就是每次启动都需要输入一遍 # node hello.js 这样很麻烦 而且一旦关闭控制台就停止运行,网站就无法打开,这是就需要使用forever模块 安装forever模块 # npm install forever -gd 通过下面的命令判断安装是否成功 # forever --help 使用forever运行hello.js项目 # forever start hello.js 这样即使关闭控制台浏览器也能正常访问 另外也可以用下面的命令运行项目 # forever sta

Spring学习(二)——使用用Gradle构建一个简单的Spring MVC Web应用程序

1.新建一个Gradle工程(Project) 在新建工程窗口的左侧中选择 [Gradle],右侧保持默认选择,点击next,模块命名为VelocityDemo. 2.在该工程下新建一个 module,在弹出的窗口的左侧中选择 [Gradle],右侧勾选[Spring MVC],如下图所示: 并勾选[Application server],下方选择框中选择Tomcat7.0,如无该选项,则选中右边的 [ New... ] -- [ Tomcat Server ], 配置 Tomcat .配置好后

构建一个简单的Spring Boot项目

11 构建一个简单的Spring Boot项目 这个章节描述如何通过Spring Boot构建一个"Hello Word"web应用,侧重介绍Spring Boot的一些重要功能.因为大多数的开发工具都支持Maven,所以我们使用它来构建这个应用. 网站 spring.io 包含了许多如何开始使用Spring Boot的指南.如果您需要解决具体的问题,可以先去这里看看.你可以跳过以下的步骤,通过 start.spring.io 网站来构建项目.这样做的话,你就可以直接编写代码啦.如果需

通过python 构建一个简单的聊天服务器

构建一个 Python 聊天服务器 一个简单的聊天服务器 现在您已经了解了 Python 中基本的网络 API:接下来可以在一个简单的应用程序中应用这些知识了.在本节中,将构建一个简单的聊天服务器.使用 Telnet,客户机可以连接到 Python 聊天服务器上,并在全球范围内相互进行通信.提交到聊天服务器的消息可以由其他人进行查看(以及一些管理信息,例如客户机加入或离开聊天服务器).这个模型如图 1 所示. 图 1. 聊天服务器使用 select 方法来支持任意多个客户机 聊天服务器的一个重要

第三周——构建一个简单的Linux系统MenuOS

[洪韶武 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ] 第三周  构建一个简单的Linux系统MenuOS

第一节 构建一个简单的WCF应用

先吐个槽,到目前为止接触的东西也就是些ado.net.select.delete.update.create.临时表的批量操作.及稍微复杂点的几个表之间查询再带几个excel导入导出 然后会点前端的js.jquery等,所以在公司目前薪水并不高(能在广州生活下去吧,什么买车买房的想都别想),拿自己身边的同志一比较感觉心里不怎么平衡,凡事还是得靠自己 自强才是硬道理,就吐到这里吧!开始我的wcf之旅吧 本人理工科类型的文笔很烂 希望各位大神不要喷小弟哦(参照的书本:WCF全面解析) 咱们还是从小学

Android学习路线(四)构建一个简单的UI

Android应用的图形化用户界面的构建使用的是View 和 ViewGroup 对象的层次嵌套. View 对象通常是UI部件,例如 buttons 或者 text fields ,而 ViewGroup 是用来定义它的子布局如何排布的容器,它通常是不可见的,例如一个网格或者一个垂直的列表. Android提供XML词汇与View或者ViewGroup的子类的对应,这样的话你就可以通过XML元素的层级嵌套来定义你的UI. 另一种布局 使用XML声明UI比在运行时代码中声明更有用处可以在很多地方