1. 程式人生 > >14.shiro單點登入

14.shiro單點登入

1.cas實現單點登入

(1)修改host檔案,設定三個本地域名分別訪問cas-server(登入中心)、app1(客戶端)、app2(客戶端)

(2)證書

生成登入伺服器端祕鑰庫


匯出登入伺服器端證書


客戶端機器(app1、app2)上匯入證書


(3)配置cas-server的tomcat

tomcat配置檔案新增:

<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol" SSLEnabled="true"  
       	       maxThreads="150" scheme="https" secure="true"  
               clientAuth="false" sslProtocol="TLS"   
               keystoreFile="D:\ssl\cas_server.keystore" keystorePass="123456"/>
驗證cas-server的tomcat配置
啟動tomcat後訪問https://www.cas_server.com:8443/如果現實貓頁面表示配置成功


安裝CAS-SERVER

下載CAS(http://www.jasig.org/cas/download),解壓cas-server-4.0.0-release.zip找到cas-server-4.0.0/modules/cas-server-webapp-4.0.0.war檔案,改名為cas.war放到tomcat下同時重新啟動tomcat訪問他的login頁面(https://www.cas_server.com:8443/cas/login)


cas4.0後預設使用者名稱密碼是casuser/Mellon,點選登入可以看到成功頁面


(4)配置cas-client1的tomcat

安裝CAS-CLIENT:

下載CAS(http://www.jasig.org/cas/download),解壓cas-client-3.3.3-release.zip找到cas-client-4.0.0/modules/cas-client-core.jar

準備一個tomcat作為子系統1,改變相關啟動埠

<Server port="18004" shutdown="SHUTDOWN"> 
<!--其他省略-->   
<Connector executor="tomcatThreadPool"
               port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    
    <Connector port="18010" protocol="AJP/1.3" redirectPort="18445" />
</Server>
使用tomcat自帶的example專案作為測試專案,將上面的cas-client-core.jar放到example專案的lib資料夾下,同時給web.xml檔案配置單點登入相關內容
<!-- ======================== 單點登入開始 ======================== -->
		<!-- 用於單點退出,該過濾器用於實現單點登出功能,可選配置-->
		<listener>
			<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
		</listener>

		<!-- 該過濾器用於實現單點登出功能,可選配置。 -->
		<filter>
			<filter-name>CAS Single Sign Out Filter</filter-name>
			<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
		</filter>
		<filter-mapping>
			<filter-name>CAS Single Sign Out Filter</filter-name>
			<url-pattern>/*</url-pattern>
		</filter-mapping>

		<filter>
			<filter-name>CAS Filter</filter-name>
			<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
			<init-param>
				<param-name>casServerLoginUrl</param-name>
				<param-value>https://www.cas_server.com:8443/cas/login</param-value>
			</init-param>
			<init-param>
				<param-name>serverName</param-name>
				<param-value>http://www.app1_server.com:18080</param-value>
			</init-param>
		</filter>
		<filter-mapping>
			<filter-name>CAS Filter</filter-name>
			<url-pattern>/*</url-pattern>
		</filter-mapping>
		<!-- 該過濾器負責對Ticket的校驗工作,必須啟用它 -->
		<filter>
			<filter-name>CAS Validation Filter</filter-name>
			<filter-class>
				org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
			<init-param>
				<param-name>casServerUrlPrefix</param-name>
				<param-value>https://www.cas_server.com:8443/cas</param-value>
			</init-param>
			<init-param>
				<param-name>serverName</param-name>
				<param-value>http://www.app1_server.com:18080</param-value>
			</init-param>
		</filter>
		<filter-mapping>
			<filter-name>CAS Validation Filter</filter-name>
			<url-pattern>/*</url-pattern>
		</filter-mapping>

		<!--
			該過濾器負責實現HttpServletRequest請求的包裹,
			比如允許開發者通過HttpServletRequest的getRemoteUser()方法獲得SSO登入使用者的登入名,可選配置。
		-->
		<filter>
			<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
			<filter-class>
				org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
		</filter>
		<filter-mapping>
			<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
			<url-pattern>/*</url-pattern>
		</filter-mapping>

    <!--
		該過濾器使得開發者可以通過org.jasig.cas.client.util.AssertionHolder來獲取使用者的登入名。
		比如AssertionHolder.getAssertion().getPrincipal().getName()。
		-->
		<filter>
			<filter-name>CAS Assertion Thread Local Filter</filter-name>
			<filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>
		</filter>
		<filter-mapping>
			<filter-name>CAS Assertion Thread Local Filter</filter-name>
			<url-pattern>/*</url-pattern>
		</filter-mapping>

		<!-- ======================== 單點登入結束 ======================== -->

(5)配置cas-client2的tomcat

準備一個tomcat作為子系統2,改變相關啟動埠

<Server port="28004" shutdown="SHUTDOWN"> 
<!--其他省略-->   
<Connector executor="tomcatThreadPool"
               port="28080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="28443" />
    
    <Connector port="28010" protocol="AJP/1.3" redirectPort="28445" />
</Server>
使用tomcat自帶的example專案作為測試專案,將上面的cas-client-core.jar放到example專案的lib資料夾下,同時給web.xml檔案配置單點登入相關內容
<!-- ======================== 單點登入開始 ======================== -->
		<!-- 用於單點退出,該過濾器用於實現單點登出功能,可選配置-->
		<listener>
			<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
		</listener>

		<!-- 該過濾器用於實現單點登出功能,可選配置。 -->
		<filter>
			<filter-name>CAS Single Sign Out Filter</filter-name>
			<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
		</filter>
		<filter-mapping>
			<filter-name>CAS Single Sign Out Filter</filter-name>
			<url-pattern>/*</url-pattern>
		</filter-mapping>

		<filter>
			<filter-name>CAS Filter</filter-name>
			<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
			<init-param>
				<param-name>casServerLoginUrl</param-name>
				<param-value>https://www.cas_server.com:8443/cas/login</param-value>
			</init-param>
			<init-param>
				<param-name>serverName</param-name>
				<param-value>http://www.app2_server.com:28080</param-value>
			</init-param>
		</filter>
		<filter-mapping>
			<filter-name>CAS Filter</filter-name>
			<url-pattern>/*</url-pattern>
		</filter-mapping>
		<!-- 該過濾器負責對Ticket的校驗工作,必須啟用它 -->
		<filter>
			<filter-name>CAS Validation Filter</filter-name>
			<filter-class>
				org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
			<init-param>
				<param-name>casServerUrlPrefix</param-name>
				<param-value>https://www.cas_server.com:8443/cas</param-value>
			</init-param>
			<init-param>
				<param-name>serverName</param-name>
				<param-value>http://www.app2_server.com:28080</param-value>
			</init-param>
		</filter>
		<filter-mapping>
			<filter-name>CAS Validation Filter</filter-name>
			<url-pattern>/*</url-pattern>
		</filter-mapping>

		<!--
			該過濾器負責實現HttpServletRequest請求的包裹,
			比如允許開發者通過HttpServletRequest的getRemoteUser()方法獲得SSO登入使用者的登入名,可選配置。
		-->
		<filter>
			<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
			<filter-class>
				org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
		</filter>
		<filter-mapping>
			<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
			<url-pattern>/*</url-pattern>
		</filter-mapping>

    <!--
		該過濾器使得開發者可以通過org.jasig.cas.client.util.AssertionHolder來獲取使用者的登入名。
		比如AssertionHolder.getAssertion().getPrincipal().getName()。
		-->
		<filter>
			<filter-name>CAS Assertion Thread Local Filter</filter-name>
			<filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>
		</filter>
		<filter-mapping>
			<filter-name>CAS Assertion Thread Local Filter</filter-name>
			<url-pattern>/*</url-pattern>
		</filter-mapping>

		<!-- ======================== 單點登入結束 ======================== -->
(6)啟動三個tomcat進行測試

單點登入

www.app1_server.com/examples/servlets/servlet/HelloWorldExample訪問子系統1,會跳轉到https://www.cas_server.com:8443/cas/login頁面,然後登入

www.app2_server.com/examples/servlets/servlet/HelloWorldExample訪問子系統2,可以無需登入

退出

https://www.cas_server.com:8443/cas/logout訪問cas-server之後,再次訪問兩個子系統就需要重新登入

獲取使用者登入資訊

import java.io.*;
import java.util.*;
import java.util.Map.Entry;
 
import javax.servlet.*;
import javax.servlet.http.*;
 
import org.jasig.cas.client.authentication.AttributePrincipal;
import org.jasig.cas.client.util.AbstractCasFilter;
import org.jasig.cas.client.validation.Assertion;
 
/**
 * CAS simple Servlet
 *
 * @author <a href="http://www.micmiu.com">Michael Sun</a>
 */
 
public class HelloWorldExample extends HttpServlet {
 
	private static final long serialVersionUID = -6593274907821061823L;
 
	@SuppressWarnings("unchecked")
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws IOException, ServletException {
		ResourceBundle rb = ResourceBundle.getBundle("LocalStrings",
				request.getLocale());
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
 
		out.println("<html>");
		out.println("<head>");
 
		String title = rb.getString("helloworld.title");
 
		out.println("<title>" + title + "</title>");
		out.println("</head>");
		out.println("<body bgcolor=\"white\">");
 
		out.println("<a href=\"../helloworld.html\">");
		out.println("<img src=\"../images/code.gif\" height=24 "
				+ "width=24 align=right border=0 alt=\"view code\"></a>");
		out.println("<a href=\"../index.html\">");
		out.println("<img src=\"../images/return.gif\" height=24 "
				+ "width=24 align=right border=0 alt=\"return\"></a>");
		out.println("<h1>" + title + "</h1>");
 
		Assertion assertion = (Assertion) request.getSession().getAttribute(
				AbstractCasFilter.CONST_CAS_ASSERTION);
 
		if (null != assertion) {
			out.println(" Log | ValidFromDate =:"
					+ assertion.getValidFromDate() + "<br>");
			out.println(" Log | ValidUntilDate =:"
					+ assertion.getValidUntilDate() + "<br>");
			Map<Object, Object> attMap = assertion.getAttributes();
			out.println(" Log | getAttributes Map size = " + attMap.size()
					+ "<br>");
			for (Entry<Object, Object> entry : attMap.entrySet()) {
				out.println("     | " + entry.getKey() + "=:"
						+ entry.getValue() + "<br>");
			}
			AttributePrincipal principal = assertion.getPrincipal();
 
			// AttributePrincipal principal = (AttributePrincipal) request
			// .getUserPrincipal();
 
			String username = null;
			out.print(" Log | UserName:");
			if (null != principal) {
				username = principal.getName();
				out.println("<span style='color:red;'>" + username
						+ "</span><br>");
			}
 
		}
 
		out.println("</body>");
		out.println("</html>");
	}
}

2.shiro整合cas

(1)server

server端直接使用cas-server-webapp做登入中心,修改其中部分程式碼自定義實現登入的相關邏輯(密碼加密方式、資料來源、資料庫方式密碼驗證),資料庫驗證自定義一個類來實現密碼匹配然後打成jar包引入cas-server中,修改cas-server的配置檔案引用這個jar包

密碼驗證cas-jdbc-1.0.0.jar

META-INF/pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.distinct</groupId>
  <artifactId>cas-jdbc</artifactId>
  <version>1.0.0</version>
  <packaging>jar</packaging>

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

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
		<dependency>
			<groupId>org.jasig.cas</groupId>
			<artifactId>cas-server-core</artifactId>
			<version>4.0.0</version>
		</dependency>

        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.5</version>
        </dependency>

        <dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
            <scope>compile</scope>
            <version>3.2.6.RELEASE</version>
		</dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <scope>compile</scope>
            <version>3.2.6.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <scope>compile</scope>
            <version>4.1.0.Final</version>
        </dependency>

	</dependencies>
</project>
META-INF/properties
#Generated by Maven
#Thu Jul 16 13:30:36 CST 2015
version=1.0.0
groupId=com.distinct
artifactId=cas-jdbc
com.distinct.cas.jdbc.AbstractJdbcUsernamePasswordAuthenticationHandler
package com.distinct.cas.jdbc;

import javax.sql.DataSource;
import javax.validation.constraints.NotNull;
import org.jasig.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler;
import org.springframework.jdbc.core.JdbcTemplate;

public abstract class AbstractJdbcUsernamePasswordAuthenticationHandler extends AbstractUsernamePasswordAuthenticationHandler
{

  @NotNull
  private JdbcTemplate jdbcTemplate;

  @NotNull
  private DataSource dataSource;

  public final void setDataSource(DataSource dataSource)
  {
    this.jdbcTemplate = new JdbcTemplate(dataSource);
    this.dataSource = dataSource;
  }

  protected final JdbcTemplate getJdbcTemplate() {
    return this.jdbcTemplate;
  }

  protected final DataSource getDataSource() {
    return this.dataSource;
  }
}
com.distinct.cas.jdbc.QueryDatabaseAuthenticationHandler
package com.distinct.cas.jdbc;

import java.io.PrintStream;
import java.security.GeneralSecurityException;
import javax.security.auth.login.AccountNotFoundException;
import javax.security.auth.login.FailedLoginException;
import javax.validation.constraints.NotNull;
import org.jasig.cas.authentication.HandlerResult;
import org.jasig.cas.authentication.PreventedException;
import org.jasig.cas.authentication.UsernamePasswordCredential;
import org.jasig.cas.authentication.handler.PasswordEncoder;
import org.jasig.cas.authentication.principal.SimplePrincipal;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;

public class QueryDatabaseAuthenticationHandler extends AbstractJdbcUsernamePasswordAuthenticationHandler
{

  @NotNull
  private String sql;

  protected final HandlerResult authenticateUsernamePasswordInternal(UsernamePasswordCredential credential)
    throws GeneralSecurityException, PreventedException
  {
    String username = credential.getUsername();
    System.err.println("======= input username:(" + username + ")");
    String encryptedPassword = getPasswordEncoder().encode(credential.getPassword());
    System.err.println("======= input password:(" + encryptedPassword + ")");
    System.out.println("======= sql:(" + this.sql + ")");
    try {
      String dbPassword = (String)getJdbcTemplate().queryForObject(this.sql, String.class, 
        new Object[] { username });

      System.err.println("++++++ dbPassword:(" + dbPassword.trim() + ")");
      if (!dbPassword.trim().equals(encryptedPassword)) {
        System.err.println("Password not match.");
        throw new FailedLoginException("Password does not match value on record.");
      }
    } catch (IncorrectResultSizeDataAccessException e) {
      if (e.getActualSize() == 0) {
        throw new AccountNotFoundException(username + " not found with SQL query");
      }
      e.printStackTrace();
      throw new FailedLoginException("Multiple records found for " + username);
    } catch (DataAccessException e) {
      e.printStackTrace();
      throw new PreventedException("SQL exception while executing query for " + username, e);
    }

    return createHandlerResult(credential, new SimplePrincipal(username), null);
  }

  public void setSql(String sql) {
    this.sql = sql;
  }
}

將cas-jdbc-1.0.0.jar引入cas-server的WEB-INF/lib中

增加cas-server配置檔案

WEB-INF/deployerConfigContext.xml

<!-- 設定密碼的加密方式,這裡使用的是MD5加密 -->
    <bean id="passwordEncoder"
      class="org.jasig.cas.authentication.handler.DefaultPasswordEncoder"
      c:encodingAlgorithm="MD5"
      p:characterEncoding="UTF-8" />

  <!-- 通過資料庫驗證身份,這個得自己去實現 -->
    <bean id="primaryAuthenticationHandler"
      class="com.distinct.cas.jdbc.QueryDatabaseAuthenticationHandler"
      p:dataSource-ref="dataSource"
      p:passwordEncoder-ref="passwordEncoder"
      p:sql="select password from t_user where account=? and status = 'active'" />
      
  <!-- 設定資料來源 -->
     <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
          <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
          <property name="url" value="jdbc:mysql://127.0.0.1:3306/db_test?useUnicode=true&characterEncoding=utf8"></property>
          <property name="username" value="root"></property>
          <property name="password" value="123456"></property>  
  </bean>

資料庫建立使用者表


SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `t_permission`
-- ----------------------------
DROP TABLE IF EXISTS `t_permission`;
CREATE TABLE `t_permission` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(32) collate utf8_unicode_ci NOT NULL,
  `status` varchar(16) collate utf8_unicode_ci NOT NULL,
  `remark` varchar(128) collate utf8_unicode_ci default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

-- ----------------------------
-- Records of t_permission
-- ----------------------------
INSERT INTO `t_permission` VALUES ('1', '查詢', 'active', null);

-- ----------------------------
-- Table structure for `t_role`
-- ----------------------------
DROP TABLE IF EXISTS `t_role`;
CREATE TABLE `t_role` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(32) collate utf8_unicode_ci NOT NULL,
  `status` varchar(16) collate utf8_unicode_ci NOT NULL,
  `remark` varchar(128) collate utf8_unicode_ci default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

-- ----------------------------
-- Records of t_role
-- ----------------------------
INSERT INTO `t_role` VALUES ('1', '管理員', 'active', null);

-- ----------------------------
-- Table structure for `t_role_permission`
-- ----------------------------
DROP TABLE IF EXISTS `t_role_permission`;
CREATE TABLE `t_role_permission` (
  `id` int(11) NOT NULL auto_increment,
  `role_id` int(11) NOT NULL,
  `permission_id` int(11) NOT NULL,
  `created` datetime NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `role_permission_index` (`role_id`,`permission_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

-- ----------------------------
-- Records of t_role_permission
-- ----------------------------
INSERT INTO `t_role_permission` VALUES ('1', '1', '1', '2016-08-22 11:42:44');

-- ----------------------------
-- Table structure for `t_user`
-- ----------------------------
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
  `id` int(11) NOT NULL auto_increment,
  `account` varchar(128) collate utf8_unicode_ci NOT NULL,
  `password` varchar(128) collate utf8_unicode_ci NOT NULL,
  `username` varchar(64) collate utf8_unicode_ci NOT NULL,
  `status` varchar(32) collate utf8_unicode_ci NOT NULL,
  `created` datetime NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `account_index` (`account`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

-- ----------------------------
-- Records of t_user
-- ----------------------------
INSERT INTO `t_user` VALUES ('1', 'admin', '1b115d01a16bf363a8da2f588b3a0297', 'admin', 'active', '2016-08-19 17:46:58');

-- ----------------------------
-- Table structure for `t_user_role`
-- ----------------------------
DROP TABLE IF EXISTS `t_user_role`;
CREATE TABLE `t_user_role` (
  `id` int(11) NOT NULL auto_increment,
  `user_id` int(11) NOT NULL,
  `role_id` int(11) NOT NULL,
  `created` datetime NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `user_role_index` (`user_id`,`role_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

-- ----------------------------
-- Records of t_user_role
-- ----------------------------
INSERT INTO `t_user_role` VALUES ('1', '1', '1', '2016-08-22 11:42:01');
(2)cas-client1

使用shiro控制權限,配置cas過濾器以及相關內容,具體如下

配置檔案:

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.distinct</groupId>
  <artifactId>spring-node-1</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  
  <properties>
  	<spring.version>4.0.5.RELEASE</spring.version>
  	<slf4j.version>1.7.7</slf4j.version>
  	<jackson.version>1.9.13</jackson.version>
  	<shiro.version>1.2.3</shiro.version>
  	<!-- 下面這些定義的屬性在mybatis-generator.xml檔案中引用 -->
	<classPathEntry.location>D:/maven/repository/mysql/mysql-connector-java/5.1.30/mysql-connector-java-5.1.30.jar</classPathEntry.location>
	<jdbc.driverClass>com.mysql.jdbc.Driver</jdbc.driverClass>
	<jdbc.connectionURL>jdbc:mysql://127.0.0.1:3306/db_test</jdbc.connectionURL>
	<jdbc.user>root</jdbc.user>
	<jdbc.password>123456</jdbc.password>
	<model.target.dir>${basedir}/src/main/java</model.target.dir>
	<mapper.target.dir>${basedir}/src/main/resources</mapper.target.dir>
	<dao.target.dir>${basedir}/src/main/java</dao.target.dir>
  </properties>
  
  <dependencies>
  
  	<!-- spring jar -->
  	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-core</artifactId>
		<version>${spring.version}</version>
	</dependency>
	<dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-context-support</artifactId>
		<version>${spring.version}</version>
	</dependency>
	
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-web</artifactId>
		<version>${spring.version}</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-webmvc</artifactId>
		<version>${spring.version}</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-jdbc</artifactId>
		<version>${spring.version}</version>
	</dependency>
	
	<!-- json jar -->
	<!-- json資料 -->
	<dependency>
		<groupId>org.codehaus.jackson</groupId>
		<artifactId>jackson-mapper-asl</artifactId>
		<version>${jackson.version}</version>
	</dependency>
	<dependency>
		<groupId>org.codehaus.jackson</groupId>
		<artifactId>jackson-core-asl</artifactId>
		<version>${jackson.version}</version>
	</dependency>
	<dependency>
		<groupId>com.fasterxml.jackson.jaxrs</groupId>
		<artifactId>jackson-jaxrs-json-provider</artifactId>
		<version>2.7.0</version>
	</dependency>
	
	<!-- jsp jar -->
	<dependency>
		<groupId>javax.servlet</groupId>
		<artifactId>servlet-api</artifactId>
		<version>2.5</version>
		<type>jar</type>
		<scope>provided</scope>
	</dependency>
	<dependency>
		<groupId>javax.servlet</groupId>
		<artifactId>jsp-api</artifactId>
		<version>2.0</version>
		<scope>provided</scope>
	</dependency>
	<dependency>
		<groupId>taglibs</groupId>
		<artifactId>standard</artifactId>
		<version>1.1.2</version>
	</dependency>
	<dependency>
		<groupId>javax.servlet</groupId>
		<artifactId>jstl</artifactId>
		<version>1.1.2</version>
	</dependency>
	
	<!-- mysql驅動包 -->
	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<version>5.1.30</version>
	</dependency>
	<!-- mybatis核心包 -->
	<dependency>
		<groupId>org.mybatis</groupId>
		<artifactId>mybatis</artifactId>
		<version>3.2.7</version>
	</dependency>
	<!-- mybatis/spring包 -->
	<dependency>
		<groupId>org.mybatis</groupId>
		<artifactId>mybatis-spring</artifactId>
		<version>1.2.2</version> 
	</dependency>
	<!-- Mybatis generator生成器 -->
	<dependency>
		<groupId>org.mybatis.generator</groupId>
		<artifactId>mybatis-generator-core</artifactId>
		<version>1.3.1</version>
	</dependency>

	<!-- 阿里巴巴資料來源包 -->
	<dependency>
		<groupId>com.alibaba</groupId>
		<artifactId>druid</artifactId>
		<version>1.0.6</version>
	</dependency> 
	
	<!-- junit-test jar -->
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.9</version>
	</dependency>
	
	<!-- log jar -->
	<dependency>
		<groupId>log4j</groupId>
		<artifactId>log4j</artifactId>
		<version>1.2.12</version>
	</dependency>
	<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> 
	</dependency>
	
	<!-- apache shiro 相關jar -->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-aspectj</artifactId>
			<version>${shiro.version}</version>
		</dependency>

		<dependency>
			<groupId>redis.clients</groupId>
			<artifactId>jedis</artifactId>
			<version>2.4.2</version>
		</dependency>

		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-spring</artifactId>
			<version>${shiro.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-core</artifactId>
			<version>${shiro.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-cas</artifactId>
			<version>${shiro.version}</version>
		</dependency>
	
  </dependencies>
  
  <build>
  	<finalName>spring-node-1</finalName>
  	
  	<plugins>
  		
  		<!-- JDK level -->
  		<plugin> 
            <groupId>org.apache.maven.plugins</groupId> 
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.1</version> 
            <configuration> 
                <source>1.7</source>
				<target>1.7</target> 
                <encoding>UTF8</encoding> 
            </configuration> 
         </plugin> 
         
        <!--  tomcat7 plugin -->
         <plugin>
			<groupId>org.apache.tomcat.maven</groupId>
			<artifactId>tomcat7-maven-plugin</artifactId>
			<version>2.1</version>
			<configuration>
				<port>8081</port>
				<uriEncoding>UTF-8</uriEncoding>
				<server>tomcat7</server>
				<path>/node1</path>
			</configuration>
		</plugin>
		
		<!-- 呼叫Maven命令:mvn mybatis-generator:generate -->
		<plugin>
			<groupId>org.mybatis.generator</groupId>
			<artifactId>mybatis-generator-maven-plugin</artifactId>
			<version>1.3.1</version>
			<configuration>
				<configurationFile>${basedir}/src/main/resources/mybatis/generateUser.xml</configurationFile>
				<verbose>true</verbose>
				<overwrite>true</overwrite>
			</configuration>
		</plugin>
  	
  	</plugins>
  </build>
  
</project>

conf/spring-shiro.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:cache="http://www.springframework.org/schema/cache"
	xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
         http://www.springframework.org/schema/cache 
         http://www.springframework.org/schema/cache/spring-cache-4.0.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-4.0.xsd">

	<!-- Shiro Filter -->
	<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
		<property name="securityManager" ref="securityManager" />
		<!-- 設定使用者的登入連結,這裡為cas登入頁面的連結地址可配置回撥地址 -->
		<property name="loginUrl" value="${shiro.loginUrl}" />
		<property name="filters">
			<map>
				<!-- 新增casFilter到shiroFilter -->
				<entry key="casFilter" value-ref="casFilter" />
				<entry key="logoutFilter" value-ref="logoutFilter" />
			</map>
		</property>
		<property name="filterChainDefinitions">
			<value>
				/shiro-cas = casFilter
				/logout = logoutFilter
				/users/** = user
			</value>
		</property>
	</bean>

	<bean id="casFilter" class="org.apache.shiro.cas.CasFilter">
		<!-- 配置驗證錯誤時的失敗頁面 -->
		<property name="failureUrl" value="${shiro.failureUrl}" />
		<property name="successUrl" value="${shiro.successUrl}" />
	</bean>

	<bean id="logoutFilter" class="org.apache.shiro.web.filter.authc.LogoutFilter">
		<!-- 配置驗證錯誤時的失敗頁面 -->
		<property name="redirectUrl" value="${shiro.logoutUrl}" />
	</bean>

	<bean id="casRealm" class="com.spring.mybatis.realm.UserRealm">
		<!-- 認證通過後的預設角色 -->
		<property name="defaultRoles" value="ROLE_USER" />
		<!-- cas服務端地址字首 -->
		<property name="casServerUrlPrefix" value="${shiro.cas.serverUrlPrefix}" />
		<!-- 應用服務地址,用來接收cas服務端票據 -->
		<property name="casService" value="${shiro.cas.service}" />
	</bean>

	<!-- Shiro's main business-tier object for web-enabled applications -->
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<!-- <property name="sessionManager" ref="sessionManager" /> -->
		<property name="subjectFactory" ref="casSubjectFactory"></property>
		<property name="realm" ref="casRealm" />
	</bean>

	<bean id="casSubjectFactory" class="org.apache.shiro.cas.CasSubjectFactory"></bean>



	<bean
		class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
		<property name="securityManager" ref="securityManager" />
	</bean>


	<!-- <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"> 
		<property name="globalSessionTimeout" value="3600000" /> <property name="sessionDAO" 
		ref="sessionDAO" /> </bean> -->

	<!-- <bean id="sessionDAO" class="com.distinct.web.session.redis.RedisSessionDAO"> 
		<property name="sessionTimeout" value="1800000" /> <property name="redisManager" 
		ref="redisManager" /> </bean> -->

	<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"></bean>

	<bean
		class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
		<property name="staticMethod"
			value="org.apache.shiro.SecurityUtils.setSecurityManager"></property>
		<property name="arguments" ref="securityManager"></property>
	</bean>

</beans>
conf/spring-mybatis.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:context="http://www.springframework.org/schema/context"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:p="http://www.springframework.org/schema/p"
	   xsi:schemaLocation="
	   http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">
	
	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
		<property name="driverClassName">
			<value>${jdbc_driverClassName}</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>20</value>
		</property>
		<!-- 初始化連線大小 -->
		<property name="initialSize">
			<value>1</value>
		</property>
		<!-- 獲取連線最大等待時間 -->
		<property name="maxWait">
			<value>60000</value>
		</property>
		<!-- 連線池最大空閒 -->
		<property name="maxIdle">
			<value>20</value>
		</property>
		<!-- 連線池最小空閒 -->
		<property name="minIdle">
			<value>3</value>
		</property>
		<!-- 自動清除無用連線 -->
		<property name="removeAbandoned">
			<value>true</value>
		</property>
		<!-- 清除無用連線的等待時間 -->
		<property name="removeAbandonedTimeout">
			<value>180</value>
		</property>
		<!-- 連線屬性 -->
		<property name="connectionProperties">
			<value>clientEncoding=UTF-8</value>
		</property>
	</bean>
	
	<!-- mybatis檔案配置,掃描所有mapper檔案 -->
	<!-- configLocation為mybatis屬性  mapperLocations為所有mapper -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"
		p:dataSource-ref="dataSource" p:mapperLocations="classpath:mapper/*.xml" />

	<!-- spring與mybatis整合配置,掃描所有dao -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"
		p:basePackage="com.spring.mybatis.dao" p:sqlSessionFactoryBeanName="sqlSessionFactory" />

	<!-- 對資料來源進行事務管理 -->
	<bean id="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
		p:dataSource-ref="dataSource" />
	  
     
</beans>

conf/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:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">
        
    
    <!-- handle the json -->
    <bean
		class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
		<property name="messageConverters">
			<list>
				<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.json.MappingJackson2HttpMessageConverter">    
				    <property name="supportedMediaTypes">    
				        <list>    
				            <value>application/json;charset=UTF-8</value>    
				       </list>    
				    </property>  
				</bean>  
			</list>
		</property>
	</bean>
	
	<!-- the HandlerAdapter must before the mvc driven -->
	<mvc:annotation-driven />
	
	<!-- match the jsp view -->
	<bean id="viewResolver"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver"
		p:prefix="/jsp/" p:suffix=".jsp" />
	
	<!-- 配置首頁 -->
	<mvc:view-controller path="/" view-name="index.jsp" />
	<!-- 靜態資源處理 -->
	<mvc:default-servlet-handler />

	<mvc:resources mapping="/**" location="/" />
	
</beans>
conf/spring-context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:context="http://www.springframework.org/schema/context"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xsi:schemaLocation="
	   http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">
       
    <context:component-scan base-package="com.spring.mybatis"/>
    
   <!--  自動注入properties屬性檔案 -->
    <bean id="configProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
	    <property name="locations">
	      <list>
	        <value>classpath:conf/jdbc.properties</value>
	        <value>classpath:conf/shiro.properties</value>
	      </list>
	    </property>
    </bean>
    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">
        <property name="properties" ref="configProperties" />
    </bean>  
    <!-- springMVC配置 -->
    <import resource="spring-mvc.xml"/>
    <!-- mybatis配置 -->
    <import resource="spring-mybatis.xml"/>
    <!-- shiro配置 -->
    <import resource="spring-shiro.xml"/>
</beans>
conf/shiro.properties
#localhost
shiro.loginUrl=http://127.0.0.1:8080/cas/login?service=http://127.0.0.1:8081/node1/shiro-cas

shiro.logoutUrl=http://127.0.0.1:8080/cas/logout?service=http://127.0.0.1:8081/node1/shiro-cas

shiro.cas.serverUrlPrefix=http://127.0.0.1:8080/cas

shiro.cas.service=http://127.0.0.1:8081/node1/shiro-cas

shiro.failureUrl=/users/loginSuccess

shiro.successUrl=/users/loginSuccess
conf/log4j.properties
 ### set log levels ###
#log4j.rootLogger = debug , stdout , D , E
log4j.rootLogger = debug , stdout , D

###  output to the console ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
#log4j.appender.stdout.layout.ConversionPattern = %d{ABSOLUTE} %5p %c{ 1 }:%L - %m%n
log4j.appender.stdout.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m%n

### Output to the log file ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = ${spring-node-1.root}/WEB-INF/logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG 
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n

### Save exception information to separate file ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = ${spring-node-1.root}/WEB-INF/logs/error.log 
log4j.appender.D.Append = true
log4j.appender.D.Threshold = ERROR 
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
conf/jdbc.properties:
jdbc_driverClassName=com.mysql.jdbc.Driver
jdbc_url=jdbc:mysql://127.0.0.1:3306/db_test?useUnicode=true&characterEncoding=utf8
jdbc_username=root
jdbc_password=123456

mapper/PermissionMapper.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="com.spring.mybatis.dao.PermissionMapper">
  <resultMap id="BaseResultMap" type="com.spring.mybatis.model.Permission">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="name" jdbcType="VARCHAR" property="name" />
    <result column="status" jdbcType="VARCHAR" property="status" />
    <result column="remark" jdbcType="VARCHAR" property="remark" />
  </resultMap>
  <sql id="Base_Column_List">
    id, name, status, remark
  </sql>
  <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from t_permission
    where id = #{id,jdbcType=INTEGER}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
    delete from t_permission
    where id = #{id,jdbcType=INTEGER}
  </delete>
  <insert id="insert" parameterType="com.spring.mybatis.model.Permission">
    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
      SELECT LAST_INSERT_ID()
    </selectKey>
    insert into t_permission (name, status, remark
      )
    values (#{name,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{remark,jdbcType=VARCHAR}
      )
  </insert>
  <insert id="insertSelective" parameterType="com.spring.mybatis.model.Permission">
    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
      SELECT LAST_INSERT_ID()
    </selectKey>
    insert into t_permission
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="name != null">
        name,
      </if>
      <if test="status != null">
        status,
      </if>
      <if test="remark != null">
        remark,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="name != null">
        #{name,jdbcType=VARCHAR},
      </if>
      <if test="status != null">
        #{status,jdbcType=VARCHAR},
      </if>
      <if test="remark != null">
        #{remark,jdbcType=VARCHAR},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="com.spring.mybatis.model.Permission">
    update t_permission
    <set>
      <if test="name != null">
        name = #{name,jdbcType=VARCHAR},
      </if>
      <if test="status != null">
        status = #{status,jdbcType=VARCHAR},
      </if>
      <if test="remark != null">
        remark = #{remark,jdbcType=VARCHAR},
      </if>
    </set>
    where id = #{id,jdbcType=INTEGER}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.spring.mybatis.model.Permission">
    update t_permission
    set name = #{name,jdbcType=VARCHAR},
      status = #{status,jdbcType=VARCHAR},
      remark = #{remark,jdbcType=VARCHAR}
    where id = #{id,jdbcType=INTEGER}
  </update>
  
  <select id="getPermissions" resultType="java.lang.String">
    SELECT tp.name 
	FROM t_user_role tur, t_user tu, t_role tr,t_permission tp, t_role_permission trp
	WHERE tur.user_id = tu.id
	AND tur.role_id = tr.id
	AND tu.status = 'active'
	AND trp.role_id = tr.id
	AND trp.permission_id = tp.id
	AND tp.status = 'active'
	AND tu.account = #{account,jdbcType=VARCHAR}
  </select>
</mapper>

mapper/RoleMapper.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="com.spring.mybatis.dao.RoleMapper">
  <resultMap id="BaseResultMap" type="com.spring.mybatis.model.Role">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="name" jdbcType="VARCHAR" property="name" />
    <result column="status" jdbcType="VARCHAR" property="status" />
    <result column="remark" jdbcType="VARCHAR" property="remark" />
  </resultMap>
  <sql id="Base_Column_List">
    id, name, status, remark
  </sql>
  <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from t_role
    where id = #{id,jdbcType=INTEGER}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
    delete from t_role
    where id = #{id,jdbcType=INTEGER}
  </delete>
  <insert id="insert" parameterType="com.spring.mybatis.model.Role">
    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
      SELECT LAST_INSERT_ID()
    </selectKey>
    insert into t_role (name, status, remark
      )
    values (#{name,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{remark,jdbcType=VARCHAR}
      )
  </insert>
  <insert id="insertSelective" parameterType="com.spring.mybatis.model.Role">
    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
      SELECT LAST_INSERT_ID()
    </selectKey>
    insert into t_role
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="name != null">
        name,
      </if>
      <if test="status != null">
        status,
      </if>
      <if test="remark != null">
        remark,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="name != null">
        #{name,jdbcType=VARCHAR},
      </if>
      <if test="status != null">
        #{status,jdbcType=VARCHAR},
      </if>
      <if test="remark != null">
        #{remark,jdbcType=VARCHAR},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="com.spring.mybatis.model.Role">
    update t_role
    <set>
      <if test="name != null">
        name = #{name,jdbcType=VARCHAR},
      </if>
      <if test="status != null">
        status = #{status,jdbcType=VARCHAR},
      </if>
      <if test="remark != null">
        remark = #{remark,jdbcType=VARCHAR},
      </if>
    </set>
    where id = #{id,jdbcType=INTEGER}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.spring.mybatis.model.Role">
    update t_role
    set name = #{name,jdbcType=VARCHAR},
      status = #{status,jdbcType=VARCHAR},
      remark = #{remark,jdbcType=VARCHAR}
    where id = #{id,jdbcType=INTEGER}
  </update>  
  <select id="getRoles" resultType="java.lang.String">
    SELECT tr.name 
	FROM t_user_role tur, t_user tu, t_role tr
	WHERE tur.user_id = tu.id
	AND tur.role_id = tr.id
	AND tu.status = 'active'
	AND tu.account = #{account,jdbcType=VARCHAR}
  </select>
  
</mapper>
mapper/RolePermission.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="com.spring.mybatis.dao.RolePermissionMapper" >
  <resultMap id="BaseResultMap" type="com.spring.mybatis.model.RolePermission" >
    <id column="id" property="id" jdbcType="INTEGER" />
    <result column="role_id" property="roleId" jdbcType="INTEGER" />
    <result column="permission_id" property="permissionId" jdbcType="INTEGER" />
    <result column="created" property="created" jdbcType="TIMESTAMP" />
  </resultMap>
  <sql id="Base_Column_List" >
    id, role_id, permission_id, created
  </sql>
  <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
    select 
    <include refid="Base_Column_List" />
    from t_role_permission
    where id = #{id,jdbcType=INTEGER}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
    delete from t_role_permission
    where id = #{id,jdbcType=INTEGER}
  </delete>
  <insert id="insert" parameterType="com.spring.mybatis.model.RolePermission" >
    <selectKey resultType="java.lang.Integer" keyProperty="id" order="AFTER" >
      SELECT LAST_INSERT_ID()
    </selectKey>
    insert into t_role_permission (role_id, permission_id, created
      )
    values (#{roleId,jdbcType=INTEGER}, #{permissionId,jdbcType=INTEGER}, #{created,jdbcType=TIMESTAMP}
      )
  </insert>
  <insert id="insertSelective" parameterType="com.spring.mybatis.model.RolePermission" >
    <selectKey resultType="java.lang.Integer" keyProperty="id" order="AFTER" >
      SELECT LAST_INSERT_ID()
    </selectKey>
    insert into t_role_permission
    <trim prefix="(" suffix=")" suffixOverrides="," >
      <if test="roleId != null" >
        role_id,
      </if>
      <if test="permissionId != null" >
        permission_id,
      </if>
      <if test="created != null" >
        created,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides="," >
      <if test="roleId != null" >
        #{roleId,jdbcType=INTEGER},
      </if>
      <if test="permissionId != null" >
        #{permissionId,jdbcType=INTEGER},
      </if>
      <if test="created != null" >
        #{created,jdbcType=TIMESTAMP},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="com.spring.mybatis.model.RolePermission" >
    update t_role_permission
    <set >
      <if test="roleId != null" >
        role_id = #{roleId,jdbcType=INTEGER},
      </if>
      <if test="permissionId != null" >
        permission_id = #{permissionId,jdbcType=INTEGER},
      </if>
      <if test="created != null" >
        created = #{created,jdbcType=TIMESTAMP},
      </if>
    </set>
    where id = #{id,jdbcType=INTEGER}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.spring.mybatis.model.RolePermission" >
    update t_role_permission
    set role_id = #{roleId,jdbcType=INTEGER},
      permission_id = #{permissionId,jdbcType=INTEGER},
      created = #{created,jdbcType=TIMESTAMP}
    where id = #{id,jdbcType=INTEGER}
  </update>
</mapper>
mapper/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="com.spring.mybatis.dao.UserMapper" >
  <resultMap id="BaseResultMap" type="com.spring.mybatis.model.User" >
    <id column="id" property="id" jdbcType="INTEGER" />
    <result column="account" property="account" jdbcType="VARCHAR" />
    <result column="password" property="password" jdbcType="VARCHAR" />
    <result column="username" property="username" jdbcType="VARCHAR" />
    <result column="status" property="status" jdbcType="VARCHAR" />
    <result column="created" property="created" jdbcType="TIMESTAMP" />
  </resultMap>
  <sql id="Base_Column_List" >
    id, account, password, username, status, created
  </sql>
  <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
    select 
    <include refid="Base_Column_List" />
    from t_user
    where id = #{id,jdbcType=INTEGER}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
    delete from t_user
    where id = #{id,jdbcType=INTEGER}
  </delete>
  <insert id="insert" parameterType="com.spring.mybatis.model.User" >
    <selectKey resultType="java.lang.Integer" keyProperty="id" order="AFTER" >
      SELECT LAST_INSERT_ID()
    </selectKey>
    insert into t_user (account, password, username, 
      status, created)
    values (#{account,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, #{username,jdbcType=VARCHAR}, 
      #{status,jdbcType=VARCHAR}, #{created,jdbcType=TIMESTAMP})
  </insert>
  <insert id="insertSelective" parameterType="com.spring.mybatis.model.User" >
    <selectKey resultType="java.lang.Integer" keyProperty="id" order="AFTER" >
      SELECT LAST_INSERT_ID()
    </selectKey>
    insert into t_user
    <trim prefix="(" suffix=")" suffixOverrides="," >
      <if test="account != null" >
        account,
      </if>
      <if test="password != null" >
        password,
      </if>
      <if test="username != null" >
        username,
      </if>
      <if test="status != null" >
        status,
      </if>
      <if test="created != null" >
        created,
      </if>
    </trim>