SpringMVC+Ibatis+SPring Security开发框架搭建

近期做一个Oauth2的demo,搭建了一个小的框架,记录下来方便自己学习。框架是基于maven管理,使用Intellij Idea搭建起来的。没有使用maven的模板管理,直接用Idea新建的project。
Intellij Idea新建maven项目示例
MavenProjectRoot(项目根目录)的pom如下

<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.0modelVersion>
  <groupId>com.xzgroupId>
  <artifactId>mavenDemoartifactId>
  <packaging>pompackaging>
  <version>1.0-SNAPSHOTversion>
  <properties>
    <spring.version>4.3.7.RELEASEspring.version>
    <mysql.version>5.1.7mysql.version>
    <conmons-lang.version>2.4conmons-lang.version>
    <servlet-api.version>2.4servlet-api.version>
    <jsp-api>2.1jsp-api>
  properties>
  <modules>
    <module>securitymodule>
  modules>
  <name>security Maven Webappname>
  <url>http://maven.apache.orgurl>
  <dependencies>
    <dependency>
      <groupId>junitgroupId>
      <artifactId>junitartifactId>
      <version>3.8.1version>
      <scope>testscope>
    dependency>
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-coreartifactId>
      <version>${spring.version}version>
    dependency>
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-webartifactId>
      <version>${spring.version}version>
    dependency>
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-beansartifactId>
      <version>${spring.version}version>
    dependency>
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-webmvcartifactId>
      <version>${spring.version}version>
    dependency>
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-contextartifactId>
      <version>${spring.version}version>
    dependency>
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-jdbcartifactId>
      <version>${spring.version}version>
    dependency>
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-txartifactId>
      <version>${spring.version}version>
    dependency>
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-ormartifactId>
      <version>3.2.7.RELEASEversion>
    dependency>
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-context-supportartifactId>
      <version>${spring.version}version>
    dependency>
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-aopartifactId>
      <version>${spring.version}version>
    dependency>
    <dependency>
      <groupId>com.mysqlgroupId>
      <artifactId>mysql-connector-javaartifactId>
      <version>${mysql.version}version>
    dependency>
    
    <dependency>
      <groupId>commons-dbcpgroupId>
      <artifactId>commons-dbcpartifactId>
      <version>1.4version>
    dependency>
    <dependency>
      <groupId>commons-langgroupId>
      <artifactId>commons-langartifactId>
      <version>${conmons-lang.version}version>
    dependency>
    <dependency>
      <groupId>javax.servletgroupId>
      <artifactId>servlet-apiartifactId>
      <version>${servlet-api.version}version>
    dependency>
    <dependency>
      <groupId>javax.servlet.jspgroupId>
      <artifactId>jsp-apiartifactId>
      <version>${jsp-api}version>
    dependency>
    <dependency>
      <groupId>commons-logginggroupId>
      <artifactId>commons-loggingartifactId>
      <version>1.2version>
    dependency>
    
    <dependency>
      <groupId>com.alibabagroupId>
      <artifactId>druidartifactId>
      <version>1.0.17version>
    dependency>
    <dependency>
      <groupId>com.yinhaigroupId>
      <artifactId>ibatisartifactId>
      <version>2.0version>
    dependency>

    <dependency>
      <groupId>log4jgroupId>
      <artifactId>log4jartifactId>
      <version>1.2.17version>
    dependency>
    <dependency>
      <groupId>org.slf4jgroupId>
      <artifactId>slf4j-apiartifactId>
      <version>1.7.12version>
    dependency>
    <dependency>
      <groupId>org.slf4jgroupId>
      <artifactId>slf4j-log4j12artifactId>
      <version>1.7.12version>
    dependency>
    <dependency>
      <groupId>commons-logginggroupId>
      <artifactId>commons-loggingartifactId>
      <version>1.2version>
    dependency>
  dependencies>
  <build>
    <finalName>securityfinalName>
    <plugins>
      
      <plugin>
        <artifactId>maven-compiler-pluginartifactId>
        <version>2.3.2version>
        <configuration>
          <source>1.7source>
          <target>1.7target>
          <encoding>UTF-8encoding>
        configuration>
      plugin>
      
      <plugin>
        <artifactId>maven-surefire-pluginartifactId>
        <version>2.7version>
        <configuration>
          <skipTests>trueskipTests>
          <testFailureIgnore>truetestFailureIgnore>
        configuration>
      plugin>
      
      <plugin>
        <artifactId>maven-enforcer-pluginartifactId>
        <version>1.1version>
        <executions>
          <execution>
            <id>enforce-toolsid>
            <goals>
              <goal>enforcegoal>
            goals>
            <configuration>
              <rules>
                <requireJavaVersion>
                  <version>[1.7.0,)version>
                requireJavaVersion>
                <requireMavenVersion>
                  <version>[3.0.2,)version>
                requireMavenVersion>
              rules>
            configuration>
          execution>
        executions>
      plugin>
    plugins>
  build>
project>

新建module,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">
    <parent>
        <artifactId>mavenDemoartifactId>
        <groupId>com.xzgroupId>
        <version>1.0-SNAPSHOTversion>
    parent>
    <modelVersion>4.0.0modelVersion>
    <artifactId>securityartifactId>
    <packaging>warpackaging>
    <name>security Maven Webappname>
    <url>http://maven.apache.orgurl>
    <dependencies>
        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>3.8.1version>
            <scope>testscope>
        dependency>
        <dependency>
            <groupId>com.alibabagroupId>
            <artifactId>fastjsonartifactId>
            <version>1.2.28version>
        dependency>
        <dependency>
            <groupId>org.springframework.securitygroupId>
            <artifactId>spring-security-configartifactId>
            <version>4.0.4.RELEASEversion>
        dependency>
        <dependency>
            <groupId>org.springframework.securitygroupId>
            <artifactId>spring-security-coreartifactId>
            <version>4.0.4.RELEASEversion>
        dependency>
        <dependency>
            <groupId>org.springframework.securitygroupId>
            <artifactId>spring-security-taglibsartifactId>
            <version>4.0.4.RELEASEversion>
        dependency>
        <dependency>
            <groupId>org.springframework.securitygroupId>
            <artifactId>spring-security-webartifactId>
            <version>4.0.4.RELEASEversion>
        dependency>
        <dependency>
            <groupId>org.springframework.securitygroupId>
            <artifactId>spring-security-aclartifactId>
            <version>4.0.4.RELEASEversion>
        dependency>
    dependencies>
    <build>
        <finalName>securityfinalName>
    build>
project>

新建的module包结构遵循maven项目标准结构,配置好sources,Resources,test,web后开始spring的配置,新建spring-context.xml做完spring的主配置文件。使用context:property-placeholder标签将properties文件加载到Spring配置文件中

<context:property-placeholder  ignore-unresolvable="true"
                                         location="classpath:config.properties,
                                             classpath:jdbc.properties"/>

上面的配置等价于下面的配置,配置后可以通过${}获取properties的值

<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:config.propertiesvalue>
                <value>classpath:jdbc.propertiesvalue>
            list>
        property>
    bean>

新建spring-mvc.xml,项目使用注解,通过context-component-scan开启包路径扫描。注意在配置文件中使用 context 命名空间之前,必须在 元素中声明 context 命名空间。

xmlns:context="http://www.springframework.org/schema/context" 

<context:component-scan base-package="com.shaun" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    context:component-scan>

这里在spring-mvc.xml中只扫描@controller,在spring-context.xml中不扫描controller,这样做是因为我们的事物配置是配置在spring主容器也就是spring-context.xml中,如果我们通过springmvc扫描@service,那么将出现事物配置失效的问题。如果我们将controller配置在Spring-context.xml中,那么我们的controller访问将出现404的情况。Spring和springmvc父子容器注解扫描问题详解
主容器中扫描路径配置


    <context:component-scan base-package="com.shaun">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    context:component-scan>

有了这两个xml,我们再在web项目描述文件中配置ContextConfigLocation和DispatcherServlet


  <context-param>
    <param-name>contextConfigLocationparam-name>
    <param-value>classpath:spring-context.xmlparam-value>
  context-param>
<servlet>
    <servlet-name>springMVC</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring/spring-mvc.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>springMVC</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>

spring-mvc.xml中配置视图解析器

id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/page/">property>
        <property name="suffix" value=".jsp">property>
    

接下来配置数据源,使用mysql数据库。新建spring-datasource.xml,并将该文件引入spring-contex.xml中


<import resource="classpath:spring/spring-datasource.xml"/>

数据源使用commons-dbcp的包,mysql的驱动包。配置如下

<bean id="datasource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName">
            <value>${jdbc.driver}value>
        property>
        <property name="url">
            <value>${jdbc.url}value>
        property>
        <property name="username">
            <value>${jdbc.username}value>
        property>
        <property name="password">
            <value>${jdbc.password}value>
        property>
        <property name="maxActive">
            <value>${jdbc.maxActive}value>
        property>
        <property name="maxWait">
            <value>${jdbc.maxWait}value>
        property>
        
        <property name="maxIdle">
            <value>${jdbc.maxIdle}value>
        property>
    bean>

jdbc.properties文件如下

#驱动包
jdbc.driver=com.mysql.jdbc.Driver
#mysqlUrl
jdbc.url=jdbc:mysql://localhost:3306/security?useUnicode=true&characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456
#最大并发连接数
jdbc.maxActive=255
#最大等待时间
jdbc.maxWait=12000
#最大空闲连接数
jdbc.maxIdle=2

接下来配置数据源的事物代理。新建spring-transaction.xml并引入spring-context.xml中。


<import resource="classpath:spring/spring-transaction.xml"/>

<bean id="dataSourceProxy" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
    
    <property name="targetDataSource" ref="datasource"/>
bean>


<bean id="dataSourceProxyTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSourceProxy"/>
bean>


<bean id="transactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
         lazy-init="false" abstract="true">
    <property name="transactionManager" ref="dataSourceProxyTransactionManager"/>
        <property name="transactionAttributes">
            <props>
                <prop key="*">PROPAGATION_REQUIRED,-AppException,-PrcException,-IllegalArgumentExceptionprop>
            props>
    property>
bean>

AppException为自定义抛出的异常。

Ibatis的配置

接下来配置Ibatis。新建spring-ibatis.xml并引入spring-context.xml中

<import resource="classpath:spring/spring-ibatis.xml"/>

ibatis的使用,通过SqlMapClientBuilder创建sqlMapClient对象,调用封装的方法。

String conf = "ibatis/IbatisSqlMapConfig.xml";
        try{
            Reader reader = Resources.getResourceAsReader(conf);
            SqlMapClient sqlMapClient = SqlMapClientBuilder.buildSqlMapClient(reader);
//            List list = sqlMapClient.queryForList("leaderI.selectLeader");
            List list = sqlMapClient.queryForList("lock.getAllLocks");

在spring里,SqlMapClientFactoryBean创建SqlMapClient bean实例,配置如下

<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
    <property name="configLocations">
        <list>
            <value>classpath:ibatis/spring-ibatis-cfg.xmlvalue>
        list>
    property>
    <property name="dataSource">
        <ref bean="dataSourceProxy"/>
    property>
bean>

创建sqlExcutor,sqlMapClientTemplate bean实例

id="sqlExcutor" class="com.ibatis.sqlmap.engine.execution.SqlExecutor"/>

id="sqlMapClientTemplate" class="org.springframework.orm.ibatis.SqlMapClientTemplate">
        <property name="sqlMapClient" ref="sqlMapClient"/>

创建Dao对象,IDao.java代码如下

package com.shaun.commons.dao;

import com.ibatis.sqlmap.client.SqlMapExecutor;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.ibatis.SqlMapClientCallback;
import org.springframework.orm.ibatis.SqlMapClientTemplate;

import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;

/**
 * @Author
 * @Description
 * @Date Created on 2017/9/6.
 */
public class IDao{

    public SqlMapClientTemplate sqlMapClientTemplate;

    public SqlMapClientTemplate getSqlMapClientTemplate() {
        return sqlMapClientTemplate;
    }

    public void setSqlMapClientTemplate(SqlMapClientTemplate sqlMapClientTemplate) {
        this.sqlMapClientTemplate = sqlMapClientTemplate;
    }

    public int delete(String statementName) throws DataAccessException {
        return this.getSqlMapClientTemplate().delete(statementName);
    }

    public int delete(String statementName, Object obj) throws DataAccessException{
        return this.getSqlMapClientTemplate().delete(statementName, obj);
    }

    public Object insert(String statementName) throws DataAccessException{
        return this.getSqlMapClientTemplate().insert(statementName);
    }

    public Object insert(String statementName, Object obj) throws DataAccessException{
        return this.getSqlMapClientTemplate().insert(statementName,obj);
    }

    public int update(String statementName) throws DataAccessException{
        return this.getSqlMapClientTemplate().update(statementName);
    }

    public int update(String statementName, Object obj) throws DataAccessException{
        return this.getSqlMapClientTemplate().update(statementName,obj);
    }

    public Object queryForObject(String statementName) throws DataAccessException{
        return this.getSqlMapClientTemplate().queryForObject(statementName);
    }

    public Object queryForObject(String statementName, Object obj) throws DataAccessException{
        return this.getSqlMapClientTemplate().queryForObject(statementName,obj);
    }

    public List queryForList(String statementName) throws DataAccessException{
        return this.getSqlMapClientTemplate().queryForList(statementName);
    }

    public List queryForList(String statementName, Object obj) throws DataAccessException{
        return this.getSqlMapClientTemplate().queryForList(statementName, obj);
    }

    public List queryForPage(String var1, Object var2, int var3, int var4){
        return this.getSqlMapClientTemplate().queryForList(var1, var2, var3, var4);
    }

    public SqlMapClientTemplate getSqlMapClientTemplateTemplate(){
        return this.getSqlMapClientTemplate();
    }

    public int insertBatch(final String statementName,final List list) throws DataAccessException{
        this.getSqlMapClientTemplate().execute(new SqlMapClientCallback() {
            public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException {
                executor.startBatch();
                Iterator var2 = list.iterator();
                while(var2.hasNext()) {
                    Object object = var2.next();
                    executor.insert(statementName, object);
                }

                executor.executeBatch();
                return null;
            }
        });
        return list.size();
    }
}

将sqlMapClientTemplate bean实例注入到IDao的SqlMapClientTemplate属性,通过setter方法注入

id="baseDao" class="com.shaun.commons.dao.IDao">
        <property name="SqlMapClientTemplate">
            <ref bean="sqlMapClientTemplate"/>
        property>

创建所有Service父类BaseDaoServiceImpl.java

import com.shaun.commons.dao.IDao;

/**
 * @Author
 * @Description
 * @Date Created on 2017/9/6.
 */
public class BaseDaoServiceImpl{
    private IDao appDao;  

    public IDao getAppDao() {
        return appDao;
    }

    public void setAppDao(IDao appDao) {
        this.appDao = appDao;
    }
}

将父类service配置到容器中

id="baseDaoService" class="com.shaun.commons.service.impl.BaseDaoServiceImpl">
    <property name="appDao">
         <ref bean="baseDao"/>
    property>

编写service 例如LoginService,service继承父类service,可以调用dao的方法,同时service通过targetSource进行了事物管理

<bean id="loginService"  parent="transactionProxy">
    <property name="target">
        <bean class="com.shaun.login.service.impl.LoginServiceImpl" parent="baseDaoService">
        bean>
    property>
bean>
package com.shaun.login.service.impl;

import com.shaun.commons.dao.IDao;
import com.shaun.commons.service.impl.BaseDaoServiceImpl;
import com.shaun.login.service.LoginService;

import java.util.Map;

/**
 * @Author
 * @Description
 * @Date Created on 2017/9/6.
 */
public class LoginServiceImpl extends BaseDaoServiceImpl implements LoginService {
    @Override
    public Map queryByUserName(String userName){
        IDao iDao = super.getAppDao();
        return (Map)iDao.queryForObject("login.queryByUserName",userName);
    }
}

这里笔者犯了一个错误,在controller中使用注解方式获取Service,发现启动时容器报错,Spring没有定义这个bean。改用ApplicationContext能获取bean。问题出在哪儿呢?

//自动注入失败
@Autowired
LoginService loginService;

//手动获取bean成功
ApplicationContext ac = new ClassPathXmlApplicationContext("spring-context.xml");
LoginService loginService = (LoginService)ac.getBean("loginService");

问题出在哪儿呢?笔者于是封装了Controller父类,BaseController

public class BaseController {
    public Object getService(String serviceName){
        WebApplicationContext wc = ContextLoader.getCurrentWebApplicationContext();
        return wc.getBean(serviceName);
    }

    @Autowired
    protected HttpServletRequest request;
}

LoginController中获取Service改用父类定义的方法获取。

LoginService loginService = (LoginService) super.getService("loginService");

这时启动容器发现异常信息NullPointerException,发现问题所在,原来是容器启动时没有装配spring的配置,在web.xml中配置监听器ContextLoaderListener。

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
  listener>

spring-sercurity的配置

首先引入spring-security的jar包。创建spring-security.xml并引入spring-contex.xml文件中。这里使用的命名空间是b:beans


<b:beans xmlns="http://www.springframework.org/schema/security"
         xmlns:b="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:mvc="http://www.springframework.org/schema/mvc"
         xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
                        http://www.springframework.org/schema/security
                        http://www.springframework.org/schema/security/spring-security-4.0.xsd  http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">

    <http pattern="/resources/**" security="none"/>
    <http pattern="/login.jsp" security="none"/>
    <http pattern="/checkUser.do" security="none"/>
    <http pattern="/loginAction.do" security="none"/>
    <http use-expressions="true" entry-point-ref="myAuthenticationEntryPoint">
        <intercept-url pattern="/**" access="isAuthenticated()"/>
        <csrf disabled="true"/>
        <custom-filter ref="myAuthenticationFilter" position="FORM_LOGIN_FILTER" />
    http>

    
    <b:bean id="myAuthenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
        <b:constructor-arg name="loginFormUrl" value="/login.jsp">b:constructor-arg>
    b:bean>

    
    <b:bean id="myAuthenticationFilter" class="com.shaun.commons.filter.MyAuthenticationFilter">
        <b:property name="authenticationManager" ref="authenticationManager" />
        <b:property name="filterProcessesUrl" value="/j_spring_security_check" />
        <b:property name="authenticationSuccessHandler">
            <b:bean class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
                <b:property name="defaultTargetUrl" value="/indexAction.do" />
            b:bean>
        b:property>
        <b:property name="authenticationFailureHandler">
            <b:bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
                <b:property name="defaultFailureUrl" value="/accessDenied.jsp" />
            b:bean>
        b:property>
    b:bean>


    <authentication-manager alias="authenticationManager">
        <authentication-provider user-service-ref="MyUserDetailsService">
            <password-encoder ref="md5Encoder">password-encoder>
        authentication-provider>
    authentication-manager>

    <b:bean id="md5Encoder" class="com.shaun.commons.util.Md5SecurityPasswordEncoder">b:bean>

    <b:bean id="MyUserDetailsService" parent="transactionProxy">
        <b:property name="target">
            <b:bean class="com.shaun.commons.service.impl.MyUserDetailServiceImpl"
                    parent="baseDaoService">b:bean>
        b:property>
    b:bean>

    
    <b:bean id="myAccessDecisionManagerBean"
            class="com.shaun.commons.filter.MyAccessDecisionManager"/>

    
    <b:bean id="securityMetadataSource"
            class="com.shaun.commons.filter.MyInvocationSecurityMetadataSource" />

b:beans>

在web.xml中配置过滤器DelegatingFilterProxy

<filter>
    <filter-name>springSecurityFilterChainfilter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxyfilter-class>
  filter>

这里笔者重写了认证过滤器myAuthenticationFilter,如果不重写,会使用UsernamePasswordAuthenticationFilter处理。在过滤器中可以加入验证码的验证等。

package com.shaun.commons.filter;

import com.shaun.commons.entity.MyUser;
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 javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @Author
 * @Description
 * @Date Created on 2017/9/11.
 */
public class MyAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        Authentication authentication = super.attemptAuthentication(request, response);
        MyUser user = (MyUser) authentication.getPrincipal();
        request.getSession().setAttribute("userName",user.getUsername());
        return authentication;
    }

    @Override
    protected String obtainPassword(HttpServletRequest request) {
        return super.obtainPassword(request);
    }

    @Override
    protected String obtainUsername(HttpServletRequest request) {
        return super.obtainUsername(request);
    }

    @Override
    protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
        super.setDetails(request, authRequest);
    }
}

为了使用自定义数据库,配置authentication-manager时使用自定义的UserDetailsService,重写loadUserByUsername方法

package com.shaun.commons.service.impl;

import com.shaun.commons.dao.IDao;
import com.shaun.commons.entity.AppRole;
import com.shaun.commons.entity.MyUser;
import com.shaun.commons.util.AppException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * @Author
 * @Description
 * @Date Created on 2017/9/8.
 */
public class MyUserDetailServiceImpl extends BaseDaoServiceImpl implements UserDetailsService {
    public MyUserDetailServiceImpl(){

    }
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        Map resMap = (Map)this.getAppDao().queryForObject("login.queryByUserName",s);
        if(resMap.isEmpty()){
            throw new UsernameNotFoundException("没有找到用户信息");
        }else {
            MyUser user = new MyUser();
            user.setUserName(resMap.get("username")+"");
            user.setPassword(resMap.get("password")+"");
            AppRole appRole = new AppRole();
            appRole.setRoleName(AppRole.ROLE_USER);
            Set set = new HashSet();
            set.add(appRole);
            user.setRoles(set);
            return user;
        }
    }
}

AppRole继承了GrantedAuthority类

package com.shaun.commons.entity;

import org.springframework.security.core.GrantedAuthority;

/**
 * @Author
 * @Description
 * @Date Created on 2017/9/8.
 */
public class AppRole implements GrantedAuthority{
    public static String ROLE_USER = "ROLE_USER";
    private String roleName;

    public String getRoleName() {
        return roleName;
    }

    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }

    @Override
    public String getAuthority() {
        return this.roleName;
    }
}

使用加密算法

package com.shaun.commons.util;


import org.springframework.security.authentication.encoding.PasswordEncoder;

/**
 * @Author
 * @Description
 * @Date Created on 2017/9/11.
 */
public class Md5SecurityPasswordEncoder implements PasswordEncoder{
    @Override
    public String encodePassword(String rawPass, Object salt) {
        if ("userNotFoundPassword".equals(rawPass)) {
            return "";
        } else {
            return Md5EncodeUtil.md5Encode(rawPass);
        }
    }

    @Override
    public boolean isPasswordValid(String encPass, String rawPass, Object salt) {
        return encPass.equals(this.encodePassword(rawPass, salt));
    }
}
package com.shaun.commons.util;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import sun.misc.BASE64Encoder;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * @Author
 * @Description
 * @Date Created on 2017/9/8.
 */
public class Md5EncodeUtil {

    public static Md5EncodeUtil instance;
    private static Log log = LogFactory.getLog(Md5EncodeUtil.class);

    static {
        instance = new Md5EncodeUtil();
    }

    public static Md5EncodeUtil getInstance(){
        return instance;
    }

    public static String md5Encode(String str){
        String beforeEncodeStr = str+"-a1b2";//偏移码(salt)-a1b2
        try{
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            BASE64Encoder base64Encoder = new BASE64Encoder();
            String encodedStr = base64Encoder.encode(md5.digest(beforeEncodeStr.getBytes("UTF-8")));
            return encodedStr;
        }catch (NoSuchAlgorithmException e){
            log.error(e);
            return null;
        }catch (UnsupportedEncodingException e){
            log.error(e);
            return null;
        }

    }
}

你可能感兴趣的:(SpringMVC+Ibatis+SPring Security开发框架搭建)