最近项目中用到了ssi+spring-security 的结构,自己在家搭建了一下这套环境。仅作记录。
项目结构:
类文件:
配置文件:
视图:
使用的maven作为依赖管理,
以下为pom文件,包含所有项目所需jar 文件:
[html] view plain copy
- < 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>archgroup </groupId>
- < artifactId>archbase </artifactId>
- < packaging>war </packaging>
- < version>0.0.1-SNAPSHOT </version>
- < name>archbase Maven Webapp </name>
- < url>http://maven.apache.org </url>
- < repositories>
- < repository>
- < id>spring-milestones </id>
- < name>Spring Milestones </name>
- < url>http://repo.spring.io/milestone </url>
- < snapshots>
- < enabled>false </enabled>
- </ snapshots>
- </ repository>
- </ repositories>
- < properties>
- < org.springframework-version>4.1.0.RELEASE </org.springframework-version>
- < org.mabatis-version>3.2.8 </org.mabatis-version>
- < org.springframework.security-version>3.2.5.RELEASE </org.springframework.security-version>
- < org.aspectj-version>1.8.1 </org.aspectj-version>
- < org.slf4j-version>1.6.1 </org.slf4j-version>
- </ properties>
- < dependencies>
- <!-- Spring -->
- < dependency>
- < groupId>org.springframework </groupId>
- < artifactId>spring-context </artifactId>
- < version>${org.springframework-version} </version>
- < exclusions>
- <!-- Exclude Commons Logging in favor of SLF4j -->
- < exclusion>
- < groupId>commons-logging </groupId>
- < artifactId>commons-logging </artifactId>
- </ exclusion>
- </ exclusions>
- </ dependency>
- < dependency>
- < groupId>org.springframework </groupId>
- < artifactId>spring-jdbc </artifactId>
- < version>${org.springframework-version} </version>
- </ dependency>
- < dependency>
- < groupId>org.springframework </groupId>
- < artifactId>spring-webmvc </artifactId>
- < version>${org.springframework-version} </version>
- </ dependency>
- <!-- AspectJ -->
- < dependency>
- < groupId>org.aspectj </groupId>
- < artifactId>aspectjrt </artifactId>
- < version>${org.aspectj-version} </version>
- </ dependency>
- < dependency>
- < groupId>org.aspectj </groupId>
- < artifactId>aspectjweaver </artifactId>
- < version>1.8.4 </version>
- </ dependency>
- <!-- Logging -->
- < dependency>
- < groupId>org.slf4j </groupId>
- < artifactId>slf4j-api </artifactId>
- < version>${org.slf4j-version} </version>
- </ dependency>
- < dependency>
- < groupId>org.slf4j </groupId>
- < artifactId>jcl-over-slf4j </artifactId>
- < version>${org.slf4j-version} </version>
- < scope>runtime </scope>
- </ dependency>
- < dependency>
- < groupId>org.slf4j </groupId>
- < artifactId>slf4j-log4j12 </artifactId>
- < version>${org.slf4j-version} </version>
- < scope>runtime </scope>
- </ dependency>
- < dependency>
- < groupId>log4j </groupId>
- < artifactId>log4j </artifactId>
- < version>1.2.16 </version>
- < scope>runtime </scope>
- </ dependency>
- <!-- @Inject -->
- < dependency>
- < groupId>javax.inject </groupId>
- < artifactId>javax.inject </artifactId>
- < version>1 </version>
- </ dependency>
- < dependency>
- < groupId>mysql </groupId>
- < artifactId>mysql-connector-java </artifactId>
- < version>5.1.34 </version>
- </ dependency>
- < dependency>
- < groupId>org.mybatis </groupId>
- < artifactId>mybatis </artifactId>
- < version>${org.mabatis-version} </version>
- </ dependency>
- < dependency>
- < groupId>org.mybatis </groupId>
- < artifactId>mybatis-spring </artifactId>
- < version>1.2.2 </version>
- </ dependency>
- < dependency>
- < groupId>commons-dbcp </groupId>
- < artifactId>commons-dbcp </artifactId>
- < version>1.4 </version>
- </ dependency>
- < dependency>
- < groupId>javax.servlet </groupId>
- < artifactId>jstl </artifactId>
- < version>1.2 </version>
- </ dependency>
- <!-- Servlet -->
- <!-- < dependency>
- < groupId>org.apache.tomcat </groupId>
- < artifactId>tomcat-servlet-api </artifactId>
- < version>7.0.30 </version>
- < scope>provided </scope>
- </ dependency>
- < dependency>
- < groupId>javax.servlet.jsp </groupId>
- < artifactId>jsp-api </artifactId>
- < version>2.1 </version>
- < scope>provided </scope>
- </ dependency>
- < dependency>
- < groupId>javax.servlet.jsp.jstl </groupId>
- < artifactId>jstl-api </artifactId>
- < version>1.2 </version>
- < exclusions>
- < exclusion>
- < groupId>javax.servlet </groupId>
- < artifactId>servlet-api </artifactId>
- </ exclusion>
- </ exclusions>
- </ dependency>
- < dependency>
- < groupId>org.glassfish.web </groupId>
- < artifactId>jstl-impl </artifactId>
- < version>1.2 </version>
- < exclusions>
- < exclusion>
- < groupId>javax.servlet </groupId>
- < artifactId>servlet-api </artifactId>
- </ exclusion>
- </ exclusions>
- </ dependency> -- >
- <!-- File Upload -->
- < dependency>
- < groupId>commons-fileupload </groupId>
- < artifactId>commons-fileupload </artifactId>
- < version>1.2.2 </version>
- </ dependency>
- < dependency>
- < groupId>commons-io </groupId>
- < artifactId>commons-io </artifactId>
- < version>2.0.1 </version>
- </ dependency>
- <!-- Security -->
- < dependency>
- < groupId>org.springframework.security </groupId>
- < artifactId>spring-security-web </artifactId>
- < version>${org.springframework.security-version} </version>
- </ dependency>
- < dependency>
- < groupId>org.springframework.security </groupId>
- < artifactId>spring-security-config </artifactId>
- < version>${org.springframework.security-version} </version>
- </ dependency>
- <!-- Test -->
- < dependency>
- < groupId>junit </groupId>
- < artifactId>junit </artifactId>
- < version>3.8.1 </version>
- < scope>test </scope>
- </ dependency>
- </ dependencies>
- < build>
- < finalName>archbase </finalName>
- </ build>
- </ project>
spring 与mybatis 集成主要配置数据源、事务管理、sqlSessionFactory 以及sqlSession
[html] view plain copy
- <? 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: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/context http://www.springframework.org/schema/context/spring-context-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
- ">
- < context:property-placeholder location ="classpath:system-config.properties"/>
- <!-- 数据源 -->
- < bean id ="dataSource" class="org.apache.commons.dbcp.BasicDataSource" >
- < property name ="driverClassName" value="${driver}" ></property >
- < property name ="url" value="${url}" ></property >
- < property name ="username" value="${username}" ></property >
- < property name ="password" value="${password}" ></property >
- </ bean>
- <!-- 事务管理配置 -->
- < bean id ="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
- < property name ="dataSource" ref="dataSource" ></property >
- </ bean>
- < tx:advice id ="txAdvice" transaction-manager="transactionManager" >
- < tx:attributes >
- < tx:method name ="query*" propagation="REQUIRED" />
- < tx:method name ="insert*" propagation="REQUIRED" />
- < tx:method name ="update*" propagation="REQUIRED" />
- </ tx:attributes>
- </ tx:advice>
- < aop:config >
- < aop:pointcut expression ="execution(* com.arch.service.*.*(..))" id="service" />
- < aop:advisor advice-ref ="txAdvice" pointcut-ref="service" />
- </ aop:config>
- <!-- 与mybatis集成 -->
- < bean id ="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" >
- < property name ="dataSource" ref="dataSource" ></property >
- < property name ="configLocation" value="classpath:mybatis/mybatis-config.xml" ></property >
- <!-- mybatis配置文件自动扫描路径 -->
- < property name ="mapperLocations" value="classpath:com/arch/dao/*/*.xml" ></property >
- </ bean>
- < bean id ="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" >
- < constructor-arg index ="0" name="sqlSessionFactory" ref= "sqlSessionFactory"></constructor-arg >
- </ bean>
- <!-- dao -->
- < bean id ="commonDao" class="com.arch.dao.CommonDao" >
- < property name ="sqlSession" ref="sqlSession" ></property >
- </ bean>
- </ beans>
springmvc使用注解,所以只需要配置扫描路径,视图处理器
[html] view plain copy
- <!-- Maps '/' requests to the 'home' view -->
- < mvc:view-controller path ="/" view-name="index" />
- < context:component-scan base-package ="com.arch.view" />
[html] view plain copy
- <!-- Enables the Spring MVC @Controller programming model -->
- < mvc:annotation-driven/>
- < resources mapping ="/views/**" location="/views/" />
- <!-- Resolves views selected for rendering by @Controllers to .jsp resources
- in the /views directory -->
- < beans:bean
- class ="org.springframework.web.servlet.view.InternalResourceViewResolver">
- < beans:property name ="prefix" value="/views/" />
- < beans:property name ="suffix" value=".jsp" />
- </ beans:bean>
- <!-- Only needed because we require fileupload in the org.springframework.samples.mvc.fileupload
- package -->
- < beans:bean id ="multipartResolver"
- class ="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
- <!-- Imports user-defined @Controller beans that process client requests -->
- < beans:import resource ="controllers.xml" />
- < task:annotation-driven />
spring security 使用了自定义的user-service 以及csrf过滤器:
[html] view plain copy
- < 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.0.xsd
- http://www.springframework.org/schema/security
- http://www.springframework.org/schema/security/spring-security.xsd">
- <!-- 登录界面不使用权限过滤 -->
- < http security ="none" pattern="/login*" ></http >
- < http>
- < http-basic />
- < intercept-url pattern ="/**" access="ROLE_USER" />
- <!-- 登录界面 -->
- < form-login login-page ="/login" default-target-url="/index"
- always-use-default-target ="true" />
- < logout />
- < csrf />
- </ http>
- <!-- 自定义user-service -->
- < beans:bean id ="userDetailService" class="com.arch.security.UserDetailService" ></beans:bean >
- <!-- 自定义权限管理,使用自己的user-service -->
- < authentication-manager>
- < authentication-provider user-service-ref ="userDetailService"> </authentication-provider>
- </ authentication-manager>
- <!-- CSRF protection. Here we only include the CsrfFilter instead of all
- of Spring Security. See http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/#csrf
- for more information on Spring Security's CSRF protection -->
- < beans:bean id ="csrfFilter" class="org.springframework.security.web.csrf.CsrfFilter" >
- < beans:constructor-arg>
- < beans:bean
- class ="org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository" />
- </ beans:constructor-arg>
- </ beans:bean>
- <!-- Provides automatic CSRF token inclusion when using Spring MVC Form
- tags or Thymeleaf. -->
- < beans:bean id ="requestDataValueProcessor"
- class ="org.springframework.security.web.servlet.support.csrf.CsrfRequestDataValueProcessor" />
- </ beans:beans>
然后就是web.xml文件了,spring 所需要的contextLoaderListener,spring-mvc需要的dispatchServlet 以及 spring-security和csrf所需要的两个过滤器
[html] view plain copy
- <? 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"
- 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>Archetype Created Web Application </display-name>
- < context-param>
- < param-name>contextConfigLocation </param-name>
- < param-value>/WEB-INF/classes/spring/root-context.xml </param-value>
- </ context-param>
- <!-- Creates the Spring Container shared by all Servlets and Filters -->
- < listener>
- < listener-class>org.springframework.web.context.ContextLoaderListener </listener-class>
- </ listener>
- < 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>
- < filter-name>csrfFilter </filter-name>
- < filter-class>org.springframework.web.filter.DelegatingFilterProxy </filter-class>
- < async-supported>true </async-supported>
- </ filter>
- < filter-mapping>
- < filter-name>csrfFilter </filter-name>
- < url-pattern>/* </url-pattern>
- </ filter-mapping>
- <!-- Processes application requests -->
- < servlet>
- < servlet-name>appServlet </servlet-name>
- < servlet-class>org.springframework.web.servlet.DispatcherServlet </servlet-class>
- < init-param>
- < param-name>contextConfigLocation </param-name>
- < param-value>/WEB-INF/classes/springweb/servlet-context.xml </param-value>
- </ init-param>
- < load-on-startup>1 </load-on-startup>
- < async-supported>true </async-supported>
- </ servlet>
- < servlet-mapping>
- < servlet-name>appServlet </servlet-name>
- < url-pattern>/ </url-pattern>
- </ servlet-mapping>
- </ web-app>
然后就是mybatis的mapper文件:
userMapping.xml
[html] view plain copy
- <? 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 ="user.mapper">
- < select id ="countAll" resultType="int" > <!-- 查询表中记录总数 -->
- select count(*) c from tb_user;
- </ select>
- < select id ="selectAll" resultType="com.arch.domain.UserInfoVo" > <!-- 查询表中的所有用户 -->
- select * from tb_user order by username asc
- </ select>
- < insert id ="insert" parameterType="com.arch.domain.UserInfoVo" > <!-- 向数据库中插入用户 -->
- insert into tb_user(id,username,password) values(#{id},#{username},#{password})
- </ insert>
- < update id ="update" parameterType="com.arch.domain.UserInfoVo" > <!-- 更新库中的用户 -->
- update tb_user set username =#{username},password=#{password} where username=#{username}
- </ update>
- < delete id ="delete" parameterType="String" > <!-- 删除用户 -->
- delete from tb_user where username =#{username}
- </ delete>
- < select id ="findByUserName" parameterType="String" resultType= "com.arch.domain.UserInfoVo"> <!-- 根据用户名查找用户 -->
- select * from tb_user where username =#{username}
- </ select>
- </ mapper>
配置到这里就已经完成了,然后就是类文件:
CommonDao:
[java] view plain copy
- public class CommonDao {
- private SqlSession sqlSession;
- public void setSqlSession(SqlSession sqlSession) {
- this .sqlSession = sqlSession;
- }
- public List selectList(String statement, Object parameter ){
- return sqlSession.selectList(statement, parameter);
- }
- public int insert(String statement, Object parameter){
- return sqlSession.insert(statement, parameter);
- }
- }
UserInfoVo
[java] view plain copy- @Repository
- public class UserInfoVo implements UserDetails{
- private static final long serialVersionUID = -739110967197874283L;
- private String id;
- private String username;
- private String password;
- public String getId() {
- return id;
- }
- public void setId(String 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;
- }
- @Override
- public String toString() {
- return "UserInfoVo [username=" + username + ", password=" + password
- + "]" ;
- }
- public Collection<? extends GrantedAuthority> getAuthorities() {
- /**
- * 测试,写死了角色
- */
- List<SimpleGrantedAuthority> authos = new ArrayList<>();
- SimpleGrantedAuthority sim = new SimpleGrantedAuthority("ROLE_USER");
- authos.add(sim);
- return authos;
- }
- public boolean isAccountNonExpired() {
- return true;
- }
- public boolean isAccountNonLocked() {
- return true;
- }
- public boolean isCredentialsNonExpired() {
- return true;
- }
- public boolean isEnabled() {
- return true;
- }
- }
UserDetailService:
[java] view plain copy
- /**
- * 这里传过来用户名,需要在此作验证,并返回实现了UserDetails接口的用户VO
- */
- @Override
- public UserDetails loadUserByUsername(String username){
- UserInfoVo user = new UserInfoVo();
- System.out.println(user);
- user.setUsername(username);
- user.setPassword("admin" );
- return user;
- }
userServiceImpl:
[java] view plain copy
- @Service ("userService")
- public class UserServiceImpl implements UserService {
- @Autowired
- private CommonDao dao;
- public List<UserInfoVo> listAll(UserInfoVo user) {
- List<UserInfoVo> users = dao.selectList("user.mapper.selectAll" , user);
- return users;
- }
- public int insert(UserInfoVo user) {
- int i = dao.insert("user.mapper.insert", user);
- return i;
- }
- }
LoginController:
[java] view plain copy
- @Controller
- public class LoginController {
- @Inject
- private UserService userService;
- @RequestMapping ("index")
- public String index(){
- List<UserInfoVo> users = userService.listAll(new UserInfoVo());
- for (UserInfoVo u : users){
- System.out.println(u);
- }
- return "index";
- }
- @RequestMapping ("login")
- public String login(){
- return "login";
- }
- }
以上。
下载地址:点击进入下载