Commit 764704c5 by liuhui

新版首页工程

parent 05805bff
Showing with 2334 additions and 0 deletions
<?xml version="1.0" encoding="UTF-8"?>
<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.sinobase</groupId>
<artifactId>sinobase-empty</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>sinobase-homepage</name>
<description>示例子工程(空)</description>
<parent>
<groupId>com.sinobase</groupId>
<artifactId>sinobase</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<profiles>
<profile>
<id>dev</id>
<properties>
<profileActive>dev</profileActive>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>test</id>
<properties>
<profileActive>test</profileActive>
</properties>
</profile>
</profiles>
<dependencies>
<!-- SpringBoot 核心包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- SpringBoot WEB依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- log4j -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j</artifactId>
<version>1.3.8.RELEASE</version>
</dependency>
<!-- SLF4J日志 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<!-- SpringBoot内部依赖json处理库(核心) -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
<!-- SpringBoot内部依赖json处理库(数据绑定) -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- SpringBoot内部依赖json处理库 (注释)-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<!-- sinobase-common -->
<dependency>
<groupId>com.sinobase</groupId>
<artifactId>sinobase-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- sinobase-datasource -->
<dependency>
<groupId>com.sinobase</groupId>
<artifactId>sinobase-datasource</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- 远程调用实现类 -->
<dependency>
<groupId>com.sinobase</groupId>
<artifactId>sinobase-transfer-dubbo</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
<!-- SpringBoot集成mybatis Plus框架 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.6</version>
</dependency>
<!-- spring 缓存支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- shiro-spring -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
</dependency>
<!-- Shiro使用EhCache缓存框架 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.crazycake/shiro-redis -->
<dependency>
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis</artifactId>
<version>3.1.0</version>
</dependency>
<!-- Mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- Oracle -->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.3</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/lib/ojdbc6.jar</systemPath>
</dependency>
<!-- json处理工具 -->
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.3</version>
<classifier>jdk15</classifier>
</dependency>
<!-- http-client -->
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<!-- 阿里JSON解析器 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>application.yml</include>
<include>application-${profileActive}.yml</include>
<include>banner.txt</include>
<include>mybatis/**/*</include>
<include>static/**/*</include>
<include>templates/**/*</include>
<include>ehcache/*</include>
<include>log4j.xml</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
# 单独部署子工程示例
## 工程结构
这是一个标准的由maven构建的java web工程。
* `pom.xml` 子工程的maven配置文件
* `src/main/java` Java代码目录
* `src/main/resources` 工程配置文件、前端文件、资源文件等
## 新增子工程操作方法
1. 复制 `sinobase-empty`到同级目录(项目根目录)并改成需要的名字。
2. 修改`pom.xml`文件中的 `<artifactId>sinobase-empty</artifactId>`
3. 在工程根目录的`pom.xml`中的`modules`节点下添加对应的子工程信息。
4. 修改`src/main/resources/application.yml`中的`server.port`(子服务端口号),并记录在根目录的README文件中
5. 修改`src/main/resources/application.yml`中的`context-path`(工和名)
6. 后期根据实际情况添加`application-xxx.yml`并修改工程中的pom.xml文件。
7. 修改文件`src/main/resources/log4j.xml`,把日志文件的名字改成对应的服务名称
经过上面的步骤子工程就添加好了,启动服务并测试访问成功,就可以进行业务代码的开发工作了。
package com.sinobase;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.ImportResource;
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
@MapperScan({"com.sinobase.empty.*.mapper"})
@ImportResource(value = {"classpath:dubbo.xml"})
public class EmptyApplication {
public static void main(String[] args){
SpringApplication.run(EmptyApplication.class, args);
}
}
package com.sinobase;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
public class EmptyServletInitializer extends SpringBootServletInitializer{
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(EmptyApplication.class);
}
}
package com.sinobase.common.bean;
import java.io.Serializable;
import java.util.LinkedHashMap;
public class User implements Serializable {
private String id; //用户Id
private String loginName; //登录名
private String userName; //用户名
private String gender; //性别
private LinkedHashMap<String, String> dept; //所在部门(第一个是当前登录时所在的部门)
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public LinkedHashMap<String, String> getDept() {
return dept;
}
public void setDept(LinkedHashMap<String, String> dept) {
this.dept = dept;
}
}
package com.sinobase.common.util;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Map;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import com.alibaba.fastjson.JSONObject;
public class HttpRequestUtil {
public static final String POST = "POST";
public static final String GET = "GET";
public static final String DEFAULT_CHARSET = "UTF-8";
private static Log log = LogFactory.getLog(HttpRequestUtil.class);
/**
* 向指定URL发送GET方法的请求
*
* @param url
* 发送请求的URL
* @param param
* 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return URL 所代表远程资源的响应结果
*/
public static String sendGet(String url, String param) {
// 默认统一对参数进行encode编码
return sendGetReq(url, param, true);
}
/**
* 向指定URL发送GET方法的请求,不进行转码
*
* @param url
* 发送请求的URL
* @param param
* 请求参数,请求参数应该是 name1=value1&name2=value2 的形式,若请求参数不是规范格式请提前对参数进行转码处理
* @return URL 所代表远程资源的响应结果
*/
public static String sendGetNoEncode(String url, String param) {
// 默认统一对参数进行encode编码
return sendGetReq(url, param, false);
}
/**
* 向指定 URL 发送POST方法的请求
*
* @param url
* 发送请求的 URL
* @param param
* 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return 所代表远程资源的响应结果
*/
public static String sendPost(String url, String param) {
// 默认统一对参数进行encode编码
return sendPostReq(url, param, true);
}
/**
* 向指定URL发送POST方法的请求,不进行转码
*
* @param url
* 发送请求的URL
* @param param
* 请求参数,请求参数应该是 name1=value1&name2=value2 的形式,若请求参数不是规范格式请提前对参数进行转码处理
* @return URL 所代表远程资源的响应结果
*/
public static String sendPostNoEncode(String url, String param) {
// 默认统一对参数进行encode编码
return sendPostReq(url, param, false);
}
/**
* 向指定URL发送GET方法的请求
*
* @param url
* 发送请求的URL
* @param param
* 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @param isEncode
* 是否要对参数进行 Encode 处理, true 进行处理 false 不进行处理
* @return URL 所代表远程资源的响应结果
*/
private static String sendGetReq(String url, String param, Boolean isEncode) {
String result = "";
InputStreamReader reader = null;
try {
String urlNameString = url;
if (StringUtils.isNotBlank(param) && isEncode) {
urlNameString = urlNameString + "?" + settingPar(param);
}
else {
urlNameString = urlNameString + "?" + param;
}
log.debug("接口请求路径:" + urlNameString);
URL realUrl = new URL(urlNameString);
// 打开和URL之间的连接
URLConnection connection = realUrl.openConnection();
// 设置通用的请求属性
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
connection.setRequestProperty("Accept-Charset", DEFAULT_CHARSET);
connection.setRequestProperty("Content-Type", "text/plain;charset=UTF-8");
connection.setReadTimeout(10000);//设置读取超时时间
connection.setConnectTimeout(10000);//设置连接超时时间
// 建立实际的连接
connection.connect();
// 获取所有响应头字段
Map<String, List<String>> map = connection.getHeaderFields();
// 遍历所有的响应头字段
for (String key : map.keySet()) {
log.debug(key + "--->" + map.get(key));
}
// 定义 BufferedReader输入流来读取URL的响应
reader = new InputStreamReader(connection.getInputStream(), DEFAULT_CHARSET);
result = reader2String(reader);
}
catch (Exception e) {
log.error("发送GET请求出现异常!", e);
}
// 使用finally块来关闭输入流
finally {
try {
if (reader != null) {
reader.close();
}
}
catch (Exception e2) {
return "";
}
}
return result;
}
/**
* 向指定 URL 发送POST方法的请求
*
* @param url
* 发送请求的 URL
* @param param
* 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @param isEncode
* 是否要对参数进行 Encode 处理, true 进行处理 false 不进行处理
*
* @return 所代表远程资源的响应结果
*/
private static String sendPostReq(String url, String param, Boolean isEncode) {
log.debug("begin post service url:" + url);
log.debug("begin post service param:" + param);
PrintWriter out = null;
BufferedReader in = null;
InputStreamReader reader = null;
String result = "";
InputStream input = null;
try {
String urlNameString = url;
if (StringUtils.isNotBlank(param) && isEncode) {
// param = settingPar(param);
urlNameString = urlNameString + "?" + settingPar(param);
}
else {
urlNameString = urlNameString + "?" + param;
}
URL realUrl = new URL(urlNameString);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
conn.setRequestProperty("Accept-Charset", DEFAULT_CHARSET);
conn.setRequestProperty("Content-Type", "text/plain;charset=UTF-8");
conn.setReadTimeout(10000);//设置读取超时时间
conn.setConnectTimeout(10000);//设置连接超时时间
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// 获取URLConnection对象对应的输出流
out = new PrintWriter(new OutputStreamWriter(conn.getOutputStream(), DEFAULT_CHARSET));
// 发送请求参数
//out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
input = conn.getInputStream();
reader = new InputStreamReader(input, DEFAULT_CHARSET);
return reader2String(reader);
}
catch (Exception e) {
log.error("发送 POST 请求出现异常!", e);
}
// 使用finally块来关闭输出流、输入流
finally {
try {
if (input != null) {
input.close();
}
if (reader != null) {
reader.close();
}
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
}
catch (IOException ex) {
return "";
}
}
return result;
}
/**
* 流转字符串
*
* @param reader
* @return
* @throws IOException
*/
private static String reader2String(Reader reader) throws IOException {
int len = 0;
char[] buf = new char[1024];
StringBuilder sb = new StringBuilder();
while ((len = reader.read(buf)) != -1) {
sb.append(new String(buf, 0, len));
}
return sb.toString();
}
/**
*
* <B>方法名称:</B><BR>
* <B>概要说明:对参数值进行转码</B><BR>
*
* @author:pangxj
* @cretetime:2018年1月11日 上午11:00:08
* @param par
* @return
* @throws UnsupportedEncodingException String
*/
private static String settingPar(String par) throws UnsupportedEncodingException {
if (StringUtils.isNotBlank(par)) {
String[] pars = par.split("&");
StringBuffer sb = new StringBuffer();
for (String pa : pars) {
String[] tempPar = pa.split("=");
if (sb.length() > 0) {
sb.append("&");
}
sb.append(tempPar[0].trim());
sb.append("=");
if (tempPar.length > 1) {
sb.append(URLEncoder.encode(tempPar[1].trim(), DEFAULT_CHARSET));
}
}
return sb.toString();
}
return "";
}
/**
*
* <B>方法名称:发起POST请求</B><BR>
* <B>概要说明:</B><BR>
*
* @param url
* 请求地址
* @param params
* 传递的参数
* @param charset
* 字符集
* @return
*/
public static String sendPost(String url, Map<String, String> params, String charset) {
String result = "";
HttpClient client = new HttpClient();
HttpMethod method = new PostMethod(url);
method.getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
method.setRequestHeader("Cookie", "special-cookie=value");
// method.setRequestHeader("", "");
// 设置Http Post数据
if (params != null) {
HttpMethodParams p = new HttpMethodParams();
for (Map.Entry<String, String> entry : params.entrySet()) {
p.setParameter(entry.getKey(), entry.getValue());
}
method.setParams(p);
}
// List<NameValuePair> nvps = new ArrayList<NameValuePair>();
// nvps.add(new BasicNameValuePair("signature", ""));
// method.setEntity(new UrlEncodedFormEntity(nvps));
try {
client.executeMethod(method);
if (method.getStatusCode() == HttpStatus.SC_OK) {
InputStream in = method.getResponseBodyAsStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in, charset));
result = reader2String(reader);
in.close();
reader.close();
}
}
catch (IOException e) {
log.error("执行HTTP Post请求" + url + "时,发生异常!", e);
}
finally {
method.releaseConnection();
}
return result;
}
/**
*
* <B>方法名称:</B><BR>
* <B>概要说明:发JSON报文用此方法</B><BR>
*
* @param url
* @param data
* @return
*/
public static String sendPostUrl(String url, String data) {
String response = null;
try {
CloseableHttpClient httpclient = null;
CloseableHttpResponse httpresponse = null;
try {
httpclient = HttpClients.createDefault();
HttpPost httppost = new HttpPost(url);
StringEntity stringentity = new StringEntity(data, ContentType.create("text/json", DEFAULT_CHARSET));
stringentity.setContentEncoding(DEFAULT_CHARSET);
httppost.setEntity(stringentity);
httpresponse = httpclient.execute(httppost);
response = EntityUtils.toString(httpresponse.getEntity(), DEFAULT_CHARSET);
}
finally {
if (httpclient != null) {
httpclient.close();
}
if (httpresponse != null) {
httpresponse.close();
}
}
}
catch (Exception e) {
log.error("发JSON报文错误", e);
}
return response;
}
/**
*
* <B>方法名称:</B><BR>
* <B>概要说明:发JSON报文用此方法</B><BR>
*
* @param url
* @param data
* @return
*/
public static String sendGetUrl(String url) {
String response = null;
try {
CloseableHttpClient httpclient = null;
CloseableHttpResponse httpresponse = null;
try {
httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet(url);
httpresponse = httpclient.execute(httpget);
response = EntityUtils.toString(httpresponse.getEntity(), DEFAULT_CHARSET);
}
finally {
if (httpclient != null) {
httpclient.close();
}
if (httpresponse != null) {
httpresponse.close();
}
}
}
catch (Exception e) {
log.error("发JSON报文错误", e);
}
return response;
}
// 发送请求
public static JSONObject httpsRequest(String requestUrl, String requestMethod) {
return httpsRequest(requestUrl, requestMethod, null);
}
public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
return JSONObject.parseObject(httpsRequestString(requestUrl, requestMethod, outputStr));
}
public static String httpsRequestString(String requestUrl, String requestMethod) {
return httpsRequestString(requestUrl, requestMethod, null);
}
public static String httpsRequestString(String requestUrl, String requestMethod, String outputStr) {
String result = "";
InputStream inputStream = null;
InputStreamReader inputStreamReader = null;
BufferedReader bufferedReader = null;
try {
TrustManager[] tm = { new JEEX509TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
conn.setSSLSocketFactory(ssf);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
conn.setRequestMethod(requestMethod);
if (null != outputStr) {
OutputStream outputStream = conn.getOutputStream();
outputStream.write(outputStr.getBytes(DEFAULT_CHARSET));
outputStream.close();
}
inputStream = conn.getInputStream();
inputStreamReader = new InputStreamReader(inputStream, DEFAULT_CHARSET);
bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
conn.disconnect();
result = buffer.toString();
}
catch (Exception e) {
log.error(e);
}
finally {
try {
if (bufferedReader != null) {
bufferedReader.close();
}
if (inputStreamReader != null) {
inputStreamReader.close();
}
if (inputStream != null) {
inputStream.close();
}
}
catch (IOException ex) {
//ex.printStackTrace();
}
}
return result;
}
public static byte[] httpsRequestByte(String requestUrl, String requestMethod) {
return httpsRequestByte(requestUrl, requestMethod, null);
}
public static byte[] httpsRequestByte(String requestUrl, String requestMethod, String outputStr) {
try {
TrustManager[] tm = { new JEEX509TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(ssf);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
conn.setRequestMethod(requestMethod);
if (null != outputStr) {
OutputStream outputStream = conn.getOutputStream();
outputStream.write(outputStr.getBytes(DEFAULT_CHARSET));
outputStream.close();
}
InputStream inputStream = conn.getInputStream();
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int n = 0;
if (inputStream != null) {
while (-1 != (n = inputStream.read(buffer))) {
output.write(buffer, 0, n);
}
inputStream.close();
}
byte[] res = new byte[output.toByteArray().length];
res = output.toByteArray();
output.close();
return res;
}
catch (Exception e) {
log.error(e);
}
return null;
}
public static String urlEnodeUTF8(String str) {
String result = str;
try {
result = URLEncoder.encode(str, DEFAULT_CHARSET);
}
catch (Exception e) {
log.error(e);
}
return result;
}
}
class JEEX509TrustManager implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
class TrustAnyHostnameVerifier implements HostnameVerifier {
public boolean verify(String hostname, SSLSession session) {
// 直接返回true
return true;
}
}
\ No newline at end of file
package com.sinobase.config;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
@Configuration
public class JacksonConfig {
@Bean
@Primary
@ConditionalOnMissingBean(ObjectMapper.class)
public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
//Include.Include.ALWAYS 默认
//Include.NON_DEFAULT 属性为默认值不序列化
//nclude.NON_EMPTY 属性为 空("") 或者为 NULL 都不序列化
//Include.NON_NULL 属性为NULL 不序列化
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
return objectMapper;
}
}
package com.sinobase.config;
import javax.sql.DataSource;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.type.JdbcType;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.MybatisXMLLanguageDriver;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.sinobase.common.utils.spring.SpringUtils;
@Configuration
public class MybatisConfig {
@Value("${mybatis-plus.mapper-location}")
private String mapperLocations;
@Bean
@ConfigurationProperties(prefix="mybatis-plus")
public MybatisSqlSessionFactoryBean sqlSessionFactoryBean() throws Exception {
MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
DataSource dataSource = SpringUtils.getBean("dynamicDataSource");
sqlSessionFactory.setDataSource(dataSource);
MybatisConfiguration configuration = new MybatisConfiguration();
configuration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
configuration.setJdbcTypeForNull(JdbcType.NULL);
sqlSessionFactory.setConfiguration(configuration);
sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
.getResources(mapperLocations));
sqlSessionFactory.setPlugins(new Interceptor[]{
new PaginationInterceptor(),
new PerformanceInterceptor(),
new OptimisticLockerInterceptor()
});
return sqlSessionFactory;
}
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
return paginationInterceptor;
}
}
package com.sinobase.config;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.servlet.Filter;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionFactory;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.sinobase.common.utils.StringUtils;
import com.sinobase.framework.shiro.filter.SSOFilter;
import com.sinobase.framework.shiro.realm.UserRealm;
import com.sinobase.framework.shiro.util.SSOProperties;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
@Configuration
@ConditionalOnProperty(prefix = "shiro", name = "cache", havingValue ="ehcache" )
public class ShiroEhcacheConfig {
private static final String loginUrl = "/login";
private static final String logoutUrl = "/logout";
@Value("${shiro.user.unauthorizedUrl}")
private String unauthorizedUrl;
@Value("${shiro.session.expireTime}")
private int expire;
@Autowired
SSOProperties ssoProperties;
@Bean
public UserRealm userRealm() {
UserRealm realm = new UserRealm();
realm.setIsPlatform(ssoProperties.getIsPlatform());
return realm;
}
@Bean
public SecurityManager securityManager(UserRealm userRealm, SessionManager ehcacheSessionManager) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(userRealm);
securityManager.setSessionManager(ehcacheSessionManager);
return securityManager;
}
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
shiroFilterFactoryBean.setLoginUrl(loginUrl);
shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
filterChainDefinitionMap.put(loginUrl, "anon");
filterChainDefinitionMap.put(logoutUrl, "anon");
filterChainDefinitionMap.put("/js", "anon");
filterChainDefinitionMap.put("/css", "anon");
filterChainDefinitionMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
//自定义filter
Map<String, Filter> filters = new LinkedHashMap<String, Filter>();
shiroFilterFactoryBean.setFilters(filters);
if(ssoProperties.getIsPlatform()) {
filters.put("ssoFilter", SSOFilter.init(ssoProperties));
filterChainDefinitionMap.put("/**", "ssoFilter");
}
return shiroFilterFactoryBean;
}
@Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}
///////////////////////////////////////////////////////////////////////////////////
@Bean
public SessionManager ehcacheSessionManager(EhCacheManager ehCacheManager, SessionDAO ehCacheDAO) {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setCacheManager(ehCacheManager);
sessionManager.setSessionDAO(null);
sessionManager.setDeleteInvalidSessions(true);
sessionManager.setSessionIdUrlRewritingEnabled(false);
sessionManager.setGlobalSessionTimeout(expire * 60 * 1000);
sessionManager.setSessionValidationSchedulerEnabled(true);
sessionManager.setSessionDAO(ehCacheDAO);
return sessionManager;
}
@Bean
public EhCacheManager ehCacheManager() {
net.sf.ehcache.CacheManager cacheManager = net.sf.ehcache.CacheManager.getCacheManager("sinobase");
EhCacheManager em = new EhCacheManager();
if(StringUtils.isNull(cacheManager)) {
em.setCacheManagerConfigFile("classpath:ehcache/ehcache-shiro.xml");
}else {
em.setCacheManager(cacheManager);
}
return em;
}
@Bean
public SessionDAO ehCacheDAO() {
SessionDAO sessionDAO = new EnterpriseCacheSessionDAO();
return sessionDAO;
}
}
package com.sinobase.config;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.servlet.Filter;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.sinobase.framework.shiro.filter.SSOFilter;
import com.sinobase.framework.shiro.realm.UserRealm;
import com.sinobase.framework.shiro.util.SSOProperties;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
@Configuration
@ConditionalOnProperty(prefix = "shiro", name = "cache", havingValue ="redis" )
public class ShiroRedisConfig {
private static final Logger logger = LoggerFactory.getLogger(ShiroRedisConfig.class);
@Value("${shiro.user.unauthorizedUrl}")
private String unauthorizedUrl;
@Value("${spring.redis.host}")
private String redisHost;
@Value("${spring.redis.port}")
private int redisPort;
@Value("${spring.redis.timeout}")
private int redisTimeout;
@Value("${spring.redis.password}")
private String redisPassword;
@Value("${shiro.session.expireTime}")
private int expire;
private static final String loginUrl = "/login";
private static final String logoutUrl = "/logout";
@Autowired
SSOProperties ssoProperties;
@Bean
public UserRealm userRealm() {
UserRealm realm = new UserRealm();
realm.setIsPlatform(ssoProperties.getIsPlatform());
return realm;
}
@Bean
public SecurityManager securityManager(UserRealm userRealm, SessionManager redisSessoinManager) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(userRealm);
securityManager.setSessionManager(redisSessoinManager);
return securityManager;
}
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
shiroFilterFactoryBean.setLoginUrl(loginUrl);
shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
filterChainDefinitionMap.put(loginUrl, "anon");
filterChainDefinitionMap.put(logoutUrl, "anon");
filterChainDefinitionMap.put("/js", "anon");
filterChainDefinitionMap.put("/css", "anon");
filterChainDefinitionMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
//自定义filter
Map<String, Filter> filters = new LinkedHashMap<String, Filter>();
shiroFilterFactoryBean.setFilters(filters);
if(ssoProperties.getIsPlatform()) {
//SSO Filter(中科软SSO服务过滤器)
filters.put("ssoFilter", SSOFilter.init(ssoProperties));
filterChainDefinitionMap.put("/**", "ssoFilter");
}
return shiroFilterFactoryBean;
}
@Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}
//////////////////////////////////////////////////////////////////////////////////////////
@Bean
public DefaultWebSessionManager redisSessoinManager(RedisSessionDAO redisSessionDAO,
RedisCacheManager redisCacheManager) {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setCacheManager(redisCacheManager);
sessionManager.setSessionDAO(redisSessionDAO);
sessionManager.setDeleteInvalidSessions(true);
sessionManager.setSessionIdUrlRewritingEnabled(false);
return sessionManager;
}
@Bean
public RedisCacheManager redisCacheManager(RedisManager redisManager) {
RedisCacheManager redisCacheManager = new RedisCacheManager();
redisCacheManager.setRedisManager(redisManager);
redisCacheManager.setExpire(expire * 60);
return redisCacheManager;
}
@Bean
public RedisSessionDAO redisSessionDAO(RedisManager redisManager) {
RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
redisSessionDAO.setRedisManager(redisManager);
return redisSessionDAO;
}
@Bean RedisManager redisManager() {
RedisManager redisManager = new RedisManager();
redisManager.setHost(redisHost);
redisManager.setPort(redisPort);
redisManager.setTimeout(redisTimeout);
redisManager.setPassword(redisPassword);
return redisManager;
}
}
package com.sinobase.empty.test.contryller;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.sinobase.empty.test.model.HouseInfo;
import com.sinobase.empty.test.service.HouseInfoService;
@Controller
public class TestController {
protected Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private HouseInfoService houseInfoService;
@RequestMapping("/test")
@ResponseBody
public List<HouseInfo> test() {
logger.debug("inner test controller");
List<HouseInfo> list = houseInfoService.getAll();
return list;
}
@RequestMapping("test2")
public String test2(){
return "/index";
}
}
package com.sinobase.empty.test.mapper;
import java.util.List;
import org.springframework.stereotype.Repository;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.sinobase.empty.test.model.HouseInfo;
@Repository
public interface HouseInfoMapper extends BaseMapper<HouseInfo>{
public List<HouseInfo> getAll();
}
package com.sinobase.empty.test.model;
public class HouseInfo {
private String id;
private String city;
private String country;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}
package com.sinobase.empty.test.service;
import java.util.List;
import com.sinobase.empty.test.model.HouseInfo;
public interface HouseInfoService {
public List<HouseInfo> getAll();
}
package com.sinobase.empty.test.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.sinobase.datasource.aspectj.lang.annotation.DataSource;
import com.sinobase.datasource.aspectj.lang.enums.DataSourceType;
import com.sinobase.empty.test.mapper.HouseInfoMapper;
import com.sinobase.empty.test.model.HouseInfo;
@Service
public class HouseInfoServiceImpl implements HouseInfoService {
@Autowired
private HouseInfoMapper houseInfoMaper;
@DataSource(DataSourceType.MASTER)
public List<HouseInfo> getAll() {
return houseInfoMaper.getAll();
}
}
# com.sinobase.framework
与工程基本结构相关的代码,如:
1. shiro的Realm
2. SSO的过滤器
3. 操作cookie的代码(平台组示例代码拿过来的)
\ No newline at end of file
package com.sinobase.framework.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.sinobase.framework.shiro.util.CookieUtil;
import com.sinobase.framework.shiro.util.SSOProperties;
import com.sinobase.framework.shiro.util.SSOUtil;
@Controller
public class SecureController {
private Logger logger = LoggerFactory.getLogger(getClass());
private static final String SSOID = "SSOID";
private static final String APP_TICKET = "app_t";
@Autowired
SSOProperties ssoProperties;
@GetMapping("/login")
public String toLogin() {
if(null != SecurityUtils.getSubject().getPrincipal()){
return "redirect:/";
}
return "login";
}
@PostMapping("/login")
public String doLogin(HttpServletRequest request, String username, String password){
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
Subject subject = SecurityUtils.getSubject();
try {
subject.login(token);
logger.debug("{} Login validate success", username);
} catch(AuthenticationException e) {
logger.debug("{} Login validate failed", username);
}
return "redirect:/";
}
@GetMapping("/logout")
public String doLogout(HttpServletRequest request, HttpServletResponse response) throws Exception {
Subject subject = SecurityUtils.getSubject();
subject.logout();
String url = request.getRequestURL().toString();
url = url.substring(0, url.lastIndexOf("/logout"));
String redirectURL = url;
if(ssoProperties.getIsPlatform()) {
String ticket = CookieUtil.getCookie(request, SSOID);
SSOUtil.init(SSOID, APP_TICKET, ssoProperties.getValidateURL()).doLogout(request, response, ticket);
CookieUtil.removeCookie(response, SSOID);
CookieUtil.removeCookie(response, APP_TICKET);
redirectURL = ssoProperties.getLoginPageURL() + "?gotoURL=" + url + "/";
}
return "redirect:/";
}
//未获授权时的页面,因为没有用到shiro权限管理,所以此方法暂时没用
@RequestMapping("/unauthorizedUrl")
public String failer() {
return "login";
}
}
package com.sinobase.framework.service;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.sinobase.common.bean.User;
import com.sinobase.transfer.service.ResourceService;
@Service
public class PlatformService {
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private ResourceService resource;
public User getUserByLoginname(String loginName) {
Map<String, Object> userMap = resource.getUserInfo(loginName, "");
User user = new User();
user.setLoginName(loginName);
user.setId(getStr(userMap, "userId"));
user.setUserName(getStr(userMap, "userFullName"));
user.setGender(getStr(userMap, "userSex"));
List<Map<String, String>> deptInfo = (List<Map<String, String>>) userMap.get("deptInfo");
LinkedHashMap<String, String> deptMap = new LinkedHashMap<String, String>();
for (Map<String, String> map : deptInfo) {
deptMap.put(map.get("deptId"), map.get("deptName"));
}
user.setDept(deptMap);
return user;
}
private String getStr(Map map, String key) {
if (map == null || map.get(key) == null) {
return "";
}
return map.get(key) + "";
}
}
package com.sinobase.framework.shiro.filter;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.sinobase.framework.shiro.util.CookieUtil;
import com.sinobase.framework.shiro.util.SSOProperties;
import com.sinobase.framework.shiro.util.SSOUtil;
public final class SSOFilter extends AccessControlFilter {
private Logger logger = LoggerFactory.getLogger(getClass());
private SSOFilter() {}
private SSOProperties ssoProperties;
//存储在浏览器端的cookie的key,因为sso服务的原因key是固定的,因此不需要在配置文件中读取,直接写成常量
private static final String SSOID = "SSOID";
private static final String APP_TICKET = "app_t";
private Long sessionExpireTime;
public SSOProperties getSsoProperties() {
return ssoProperties;
}
public void setSsoProperties(SSOProperties ssoProperties) {
this.ssoProperties = ssoProperties;
this.sessionExpireTime = Long.valueOf(ssoProperties.getSessionExpireTime() * 60 * 1000);
}
public static SSOFilter init(SSOProperties ssoProperties) {
SSOFilter ssoFilter = new SSOFilter();
ssoFilter.setSsoProperties(ssoProperties);
return ssoFilter;
}
private boolean isStaticResource(String servletPath) {
//js, css, images
String arrayPath[] = new String[] {"/js","/css","/images"};
List<String> resourcePath = Arrays.asList(arrayPath);
for(String path : resourcePath) {
int position = servletPath.indexOf(path);
if(position == 0) {
return true;
}
}
return false;
}
//判断是否拦截,false拦截,true放行
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
throws Exception {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String servletPath = httpRequest.getServletPath();
if(isStaticResource(servletPath)) { //如果请求静态文件直接放行
return true;
}
return false;
}
//上面方法拦截后,会进这个方法
//这个方法返回false表示处理完毕(不放行)
//返回true表示需要继续处理(放行)
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String servletPath = httpRequest.getServletPath();
String url = httpRequest.getRequestURL().toString();
if(servletPath.indexOf(this.ssoProperties.getSetCookie()) == 0) { //处理setCookie请求
logger.debug("/setCookie was received.");
SSOUtil.init(SSOID, APP_TICKET, ssoProperties.getValidateURL()).setCookie(httpRequest, httpResponse);
}else { //一般请求
String ticket = CookieUtil.getCookie(httpRequest, SSOID);
String appTicket = CookieUtil.getCookie(httpRequest, APP_TICKET);
//根据 ticket 和 appTicket 检测是否已经登录。如果已经登录放行(return true)
if (null != appTicket && !"".equals(ticket)) {
String[] arr = appTicket.split("-");
if (arr.length == 2) { //验证cookie是否还有效,如果有效直接放行
Long currTime = Calendar.getInstance().getTimeInMillis();
Long diffTime = currTime - Long.valueOf(arr[0]);
if(diffTime < sessionExpireTime) {
return true;
}
}
}
//如果上面没有return true(cookie已失效或没有cookie记录),清除cookie记录并redirect到sso的登录界面
CookieUtil.removeCookie(httpResponse, SSOID);
CookieUtil.removeCookie(httpResponse, APP_TICKET);
Subject subject = getSubject(httpRequest, httpResponse);
subject.logout();
String loginUrl = ssoProperties.getLoginPageURL() + "?gotoURL=" + url;
httpResponse.sendRedirect(loginUrl);
}
return false;
}
}
package com.sinobase.framework.shiro.realm;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.sinobase.common.bean.User;
import com.sinobase.framework.service.PlatformService;
public class UserRealm extends AuthorizingRealm {
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
PlatformService platformService;
private boolean isPlatform;
public void setIsPlatform(boolean isPlatform) {
this.isPlatform = isPlatform;
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
String username = token.getUsername();
String password = new String(token.getPassword());
logger.debug("username: {} will validate" , username);
User user = new User();
if(isPlatform) { //如果集成SSO登录
user = platformService.getUserByLoginname(username);
return new SimpleAuthenticationInfo(user, password, getName());
}else { //如果没有集成sso的情况下,需要开发者自行验证用户信息
if("developer".equals(username) && "123456".equals(password)) {
return new SimpleAuthenticationInfo(user, password, getName());
}
}
return null;
}
}
package com.sinobase.framework.shiro.util;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 操作cookie工具类
* 这个类里的方法是从平台组给的示例工程里拿来的,可能适当做了修改
* @author daveh
*
*/
public class CookieUtil {
public static String getCookie(HttpServletRequest request, String cookieName) {
Cookie[] cookies = request.getCookies();
String cookieValue = null;
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals(cookieName)) {
cookieValue = cookie.getValue();
break;
}
}
}
return cookieValue;
}
public static void removeCookie(HttpServletResponse response, String cookieName) {
Cookie cookie = new Cookie(cookieName, null);
cookie.setMaxAge(0);
cookie.setPath("/");
cookie.setSecure(false);
response.addCookie(cookie);
}
public static void setCookie(HttpServletResponse response, String cookieName,
String cookieValue, int expiry) {
Cookie cookie = new Cookie(cookieName, cookieValue);
cookie.setMaxAge(expiry);
cookie.setPath("/");
response.addCookie(cookie);
}
}
package com.sinobase.framework.shiro.util;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class SSOProperties {
@Value("${shiro.sso.loginPageURL}")
private String loginPageURL;
@Value("${shiro.sso.validateURL}")
private String validateURL;
@Value("${shiro.sso.setCookie}")
private String setCookie;
@Value("${shiro.session.expireTime}")
private int sessionExpireTime;
@Value("${sinobase.isPlatform}")
private boolean isPlatform;
public String getLoginPageURL() {
return loginPageURL;
}
public String getValidateURL() {
return validateURL;
}
public String getSetCookie() {
return setCookie;
}
public int getSessionExpireTime() {
return sessionExpireTime;
}
public boolean getIsPlatform() {
return isPlatform;
}
}
package com.sinobase.framework.shiro.util;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Calendar;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import com.sinobase.common.util.HttpRequestUtil;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
public class SSOUtil {
private static SSOUtil instance;
private String ssoid;
private String appTicket;
private String validateURL;
private SSOUtil(String ssoid, String appTicket, String validateURL) {
this.ssoid = ssoid;
this.appTicket = appTicket;
this.validateURL = validateURL;
}
/**
* 初始化SSOUtil实例,如果已经初始化,则init方法中的参数将不再被重新赋值
* @param ssoid
* @param appTicket
* @param validateURL
* @return
*/
public static SSOUtil init(String ssoid, String appTicket, String validateURL) {
if(null == instance) {
instance = new SSOUtil(ssoid, appTicket, validateURL);
}
return instance;
}
public void doLogout(HttpServletRequest request, HttpServletResponse response, String ticket)
throws IOException, ServletException{
NameValuePair[] params = new NameValuePair[2];
params[0] = new NameValuePair("action", "doLogout");
params[1] = new NameValuePair("cookieName", ticket);
try {
post(params);
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
public void setCookie(HttpServletRequest request, HttpServletResponse response) throws Exception {
if ("0".equals(request.getParameter("expiry"))) {
CookieUtil.removeCookie(response, ssoid);
CookieUtil.removeCookie(response, appTicket);
}else {
Boolean flag = setTicket(request, response);
// 票据设置成功
if (flag) {
String gotoURL = request.getParameter("gotoURL");
String ticket = request.getParameter("ticket");
JSONObject userinfo = getUserInfoByTK(ticket);
if(null != gotoURL) {
gotoURL = java.net.URLDecoder.decode(gotoURL, "UTF-8");
UsernamePasswordToken token = new UsernamePasswordToken(userinfo.getString("username") + "","111111", false);
Subject subject = SecurityUtils.getSubject();
subject.login(token);
response.sendRedirect(gotoURL);
}
}
}
}
public Boolean setTicket(HttpServletRequest request, HttpServletResponse response) throws Exception {
Long currTime = Calendar.getInstance().getTimeInMillis();
String ticket = request.getParameter("ticket");
JSONObject userinfo = getUserInfoByTK(ticket);
Boolean flag = false;
if (userinfo != null) {
String userid = userinfo.get("userid").toString();
String username = userinfo.get("username").toString();
String appTicket = currTime + "-" + userid;
CookieUtil.setCookie(response, this.appTicket, appTicket, -1);
CookieUtil.setCookie(response, "USER_NAME", URLEncoder.encode(username, "utf-8"), -1);
CookieUtil.setCookie(response, ssoid, ticket, -1);
flag = true;
}
return flag;
}
public JSONObject getUserInfoByTK(String ticket) throws JSONException, IOException, ServletException {
JSONObject userinfo = null;
NameValuePair[] params = new NameValuePair[2];
params[0] = new NameValuePair("action", "authTicket");
params[1] = new NameValuePair("cookieName", ticket);
JSONObject result = post(params);
if (!result.getBoolean("error")) {// 验证票据失败
userinfo = result.getJSONObject("user");
}
return userinfo;
}
public JSONObject post(NameValuePair[] params) throws IOException, ServletException, JSONException {
if(validateURL.indexOf("https") != -1) {
String requestUrl = validateURL + "/" + params[0].getValue() + "?" + params[1].getName() + "=" + params[1].getValue();
String json = HttpRequestUtil.httpsRequest(requestUrl,HttpRequestUtil.POST).toJSONString();
return new JSONObject().fromObject(json);
}else {
HttpClient httpClient = new HttpClient();
PostMethod postMethod = new PostMethod(validateURL + "/" + params[0].getValue());
postMethod.addParameters(params);
int resultCode = httpClient.executeMethod(postMethod);
switch (resultCode) {
case HttpStatus.SC_OK:
return new JSONObject().fromObject(postMethod.getResponseBodyAsString());
default:
// 其它处理
return null;
}
}
}
}
No preview for this file type
spring:
redis:
host: 152.136.74.6
port: 6379
password: bug48625
#连接超时时间(毫秒)
timeout: 2000
pool:
#最大连接数(负数表示没有限制)
max-active: 1000
#最大空闲连接
max-idle: 10
#最大阻塞等待时间(负数表示没有限制)
max-wait: 100000
database: 0
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
master:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://152.136.74.6:3306/sinooa?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
username: root
password: bug48625
# 初始连接数
initial-size: 2
# 最大连接池数量
max-active: 100
# 最小连接池数量
min-idle: 2
slave:
driver-class-name: com.mysql.cj.jdbc.Driver
enabled: false
url: jdbc:mysql://152.136.74.6:3306/davehan?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
username: davehan
password: bug48625
# 初始连接数
initial-size: 2
# 最大连接池数量
max-active: 100
# 最小连接池数量
min-idle: 2
oracle:
driver-class-name: oracle.jdbc.OracleDriver
enabled: true
url: jdbc:oracle:thin:@111.204.29.117:1521:orcl
username: sysfw
password: sysfw
# 初始连接数
initial-size: 2
# 最大连接池数量
max-active: 100
# 最小连接池数量
min-idle: 2
# 配置获取连接等待超时的时间
maxWait: 60000
# 打开PSCache,并且指定每个连接上PSCache的大小
pool-prepared-statements: true
maxPoolPreparedStatementPerConnectionSize: 20
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
maxEvictableIdleTimeMillis: 900000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
statViewServlet:
enabled: true
url-pattern: /monitor/druid/*
filter:
stat:
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: false
wall:
config:
multi-statement-allow: true
shiro:
## redis or ehcache
cache: redis
user:
unauthorizedUrl: /failed
session:
expireTime: 30
sso:
loginPageURL: "http://111.204.29.117:8500/sso"
validateURL: "http://111.204.29.117:8500/sso/ticket"
setCookie: /setCookie
workflow:
# 旧平台远程工作流提交
workflowurl: http://111.204.29.117:7001/workflow/workflow-convert.jsp
flowChartIp: http://111.204.29.117:18003
workflowMobileIP: http://111.204.29.117:7001
\ No newline at end of file
spring:
redis:
host: 152.136.74.6
port: 6379
password: bug48625
#连接超时时间(毫秒)
timeout: 2000
pool:
#最大连接数(负数表示没有限制)
max-active: 1000
#最大空闲连接
max-idle: 10
#最大阻塞等待时间(负数表示没有限制)
max-wait: 100000
database: 0
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
master:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://152.136.74.6:3306/sinooa?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
username: root
password: bug48625
# 初始连接数
initial-size: 2
# 最大连接池数量
max-active: 100
# 最小连接池数量
min-idle: 2
slave:
driver-class-name: com.mysql.cj.jdbc.Driver
enabled: false
url: jdbc:mysql://152.136.74.6:3306/davehan?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
username: davehan
password: bug48625
# 初始连接数
initial-size: 2
# 最大连接池数量
max-active: 100
# 最小连接池数量
min-idle: 2
oracle:
driver-class-name: oracle.jdbc.OracleDriver
enabled: true
url: jdbc:oracle:thin:@111.204.29.117:1521:orcl
username: sysfw
password: sysfw
# 初始连接数
initial-size: 2
# 最大连接池数量
max-active: 100
# 最小连接池数量
min-idle: 2
# 配置获取连接等待超时的时间
maxWait: 60000
# 打开PSCache,并且指定每个连接上PSCache的大小
pool-prepared-statements: true
maxPoolPreparedStatementPerConnectionSize: 20
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
maxEvictableIdleTimeMillis: 900000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
statViewServlet:
enabled: true
url-pattern: /monitor/druid/*
filter:
stat:
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: false
wall:
config:
multi-statement-allow: true
shiro:
## redis or ehcache
cache: ehcache
user:
unauthorizedUrl: /failed
session:
expireTime: 30
sso:
loginPageURL: "http://111.204.29.117:8500/sso"
validateURL: "http://111.204.29.117:8500/sso/ticket"
setCookie: /setCookie
\ No newline at end of file
# 项目相关配置
sinobase:
# 是否集成公司的微服务平台
isPlatform: true
# 开发环境配置
server:
# 服务端口
port: 8400
servlet:
# 项目contextPath
context-path: /empty
spring:
profiles:
active: @profileActive@
thymeleaf:
mode: HTML
prefix: classpath:/templates/
suffix: .html
encoding: UTF-8
content-type: text/html
cache: false
mybatis-plus:
mapper-location: classpath*:mybatis/**/*Mapper.xml ##默认是mapper-locations,这里是自定义的属性,在DruidConfig中读取
#实体扫描,多个package用逗号或者分号分隔
typeAliasesPackage: com.sinobase.project
global-config:
# 数据库相关配置
db-config:
#主键类型 AUTO:"数据库ID自增", INPUT:"用户输入ID",ID_WORKER:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID";
id-type: input
table-prefix: app_
#字段策略 IGNORED:"忽略判断",NOT_NULL:"非 NULL 判断"),NOT_EMPTY:"非空判断"
field-strategy: NOT_EMPTY
#驼峰下划线转换
column-underline: true
#数据库大写下划线转换
#capital-mode: true
#逻辑删除配置
#logic-delete-value: 0
#logic-not-delete-value: 1
#刷新mapper 调试神器
refresh: true
# 原生配置
configuration:
map-underscore-to-camel-case: true
cache-enabled: false
<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="sinobase" updateCheck="false">
<!-- 磁盘缓存位置 -->
<diskStore path="java.io.tmpdir"/>
<!-- 默认缓存 -->
<defaultCache
maxEntriesLocalHeap="1000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="3600"
overflowToDisk="false">
</defaultCache>
<!-- 登录记录缓存 锁定10分钟 -->
<cache name="loginRecordCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="600"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache>
</ehcache>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//LOGGER" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<!-- Appenders -->
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d - %-5p: %c - %m%n" />
</layout>
</appender>
<appender name="file" class="org.apache.log4j.DailyRollingFileAppender">
<param name="Encoding" value="UTF-8" />
<param name="File" value="~/sino_log/empty.log" />
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d - %-5p: %c - %m%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="LevelMax" value="ERROR"/>
<param name="LevelMin" value="DEBUG"/>
</filter>
</appender>
<!-- 3rdparty Loggers -->
<logger name="org.springframework.core">
<level value="info" />
</logger>
<logger name="org.springframework.beans">
<level value="info" />
</logger>
<logger name="org.springframework.context">
<level value="info" />
</logger>
<logger name="org.springframework.web">
<level value="info" />
</logger>
<logger name="org.mybatis">
<level value="info" />
</logger>
<logger name="com.sinosoft.sinoep">
<level value="error"/>
</logger>
<logger name="com.sinobase">
<level value="debug"/>
</logger>
<!-- Root Logger -->
<root>
<priority value="warn" />
<appender-ref ref="console" />
</root>
</log4j:configuration>
<?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.sinobase.empty.test.mapper.HouseInfoMapper">
<resultMap type="com.sinobase.empty.test.model.HouseInfo" id="houseInfoMap">
<id column="id" property="id"/>
<result column="CITY" property="city" jdbcType="VARCHAR"/>
<result column="COUNTY" property="country" jdbcType="VARCHAR"/>
</resultMap>
<sql id="field_all">
ID, CITY, COUNTY
</sql>
<select id="getAll" resultMap="houseInfoMap">
select <include refid="field_all"/>
from app_house_info
</select>
</mapper>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>index</title>
</head>
<body>
<p>index page</p>
<div shiro:principal property="userName"></div>
</body>
</html>
\ No newline at end of file
<!doctype html>
<html lang="zh_CN">
<head>
<meta charset="utf-8">
<title>Login Page</title>
<style type="text/css">
body { font-size: 14px; }
.login-container {
position: absolute;
top: 10rem;
right: 2rem;
border: 1px solid #e2ffe7;
padding: 1.5rem;
text-align: cennter;
border-radius: .3rem;
}
.login-container input {
width: 23rem;
height: 2.3rem;
margin: .5rem 0 .7rem 0;
border: 1px solid #cfcfcf;
border-radius: .3rem;
padding: .2rem .5rem .2rem;
}
.login-container button {
width: 24rem;
height: 2.3rem;
border: 1px solid #2ebc4f;
background-color: #2ebc4f;
border-radius: .1rem;
font-weight: bold;
font-size: 1.1rem;
color: #fff;
}
</style>
</head>
<body>
<form th:action="@{/login}" method="post">
<div class="login-container">
<div>
<input type="text" name="username" placeholder="Please input you UserName">
</div>
<div>
<input type="password" name="password" placeholder="Please input you Password">
</div>
<div>
<button>Sign up</button>
</div>
<div style="color:red;">
<span>用户名: developer, 密码: 123456</span>
</div>
</div>
</form>
</body>
</html>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment