提交 3e08197a authored 作者: 陈世营's avatar 陈世营

loit-core

上级 b1a419f3
<?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">
<parent>
<artifactId>loit-core</artifactId>
<groupId>com.loit</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>loit-core-cas</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package com.loit.loitcasclient.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RibbonConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
package com.loit.loitcasclient.controller;
import com.loit.loitcasclient.config.ClientAppConfig;
import com.loit.loitcasclient.service.ClientLoginService;
import com.loit.loitcasclient.utils.*;
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.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@Controller
@RequestMapping(value = "cas")
public class ClientLoginController {
@Autowired
private RestTemplate restTemplate;
@Autowired(required = false)
private ClientAppConfig clientAppConfig;
@Autowired
private ClientUserUtil userUtil;
@Autowired
private ClientLoginService clientLoginService;
protected Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private LoitLog log;
/**
* 免登录入口
* 页面自动填充参数模拟点击登录按钮
* 登录服务器需要配置门户的login/free验证接口
*/
@RequestMapping(value = "login/free", method = RequestMethod.GET)
public void loginFree(
@RequestParam(value="username",required = true) String username,
@RequestParam(value="password",required = true) String password,
HttpServletResponse response) {
clientLoginService.loginFree(username, password, response);
}
/**
* 登录入口
* 采用预登录,预登录链接可被收藏
*/
@RequestMapping(value = "login/index", method = RequestMethod.GET)
public void loginFree(
HttpServletResponse response) {
clientLoginService.loginFree(null, null, response);
}
/**
* 登录入口
* 登录页面需要手动输入用户名密码验证码
*/
@RequestMapping(value = "login", method = RequestMethod.GET)
public void login(
@RequestParam(value="url",required = false) String url,
HttpServletResponse response,HttpServletRequest request) {
clientLoginService.login(url, response);
}
/**
* 获取令牌
*/
@RequestMapping(value = "accessToken", method = RequestMethod.GET)
public void accessToken(
@RequestParam("code") String code,
HttpServletResponse response,
HttpServletRequest request) throws IOException {
String accessTokenUrl = clientAppConfig.accessTokenUrl().replace("{code}", code);
log.info("ClientLoginController accessToken() accessTokenUrl:" + accessTokenUrl);
String accessToken = ClientTokenUtil.accessToken(accessTokenUrl, restTemplate);
log.info("accessToken:"+accessToken);
response.addCookie(ClientCookieUtil.instance("accessToken", accessToken, clientAppConfig.getAccessTokenCookieTimOut()));
String url = ClientBase64Util.decoder(ClientCookieUtil.get(request.getCookies(), "url"));
log.info("ClientLoginController accessToken() Redirect url 获取令牌后重定向至:"+url);
response.sendRedirect(url);
}
/**
* 登出
*/
@ResponseBody
@RequestMapping(value = "logout", method = RequestMethod.GET)
public void logout(HttpServletResponse response) throws IOException {
// cookie 里设置门户首页url
log.info("cookie 里设置门户首页url"+clientAppConfig.getPortalIndexUrl());
response.addCookie(ClientCookieUtil.instance("url", ClientBase64Util.encoder(clientAppConfig.getPortalIndexUrl()), clientAppConfig.getAccessTokenCookieTimOut()));
// 跳转到登陆接口
log.info("ClientLoginController logout() Redirect logoutUrl 登出后重定向至:"+clientAppConfig.logoutUrl());
response.sendRedirect(clientAppConfig.logoutUrl());
// clientLoginService.logout(response);
}
// /**
// * 登出后跳转到登录页, 登录成功后跳转到门户首页
// */
// @RequestMapping(value = "logoutIndex", method = RequestMethod.GET)
// public void logoutIndex(HttpServletResponse response) throws IOException {
// // cookie 里设置门户首页url
// response.addCookie(ClientCookieUtil.instance("url", ClientBase64Util.encoder(clientAppConfig.getPortalIndexUrl()), clientAppConfig.getAccessTokenCookieTimOut()));
//
// // 跳转到登陆接口
// String codeUrl = clientAppConfig.getCasServerUrl() + "/cas/login";
// response.sendRedirect(codeUrl);
// }
/**
* 获取登录用户名-从cookie中获取
*/
@ResponseBody
@RequestMapping(value = "userId/cookie", method = RequestMethod.GET)
public Map userId(HttpServletRequest request) {
String accessToken = ClientCookieUtil.get(request.getCookies(), "accessToken");
String userName = userUtil.getUserId(accessToken);
Map<String, Object> map = new HashMap<>();
map.put("userName", userName);
return map;
}
/**
* 获取登录用户名-从登录服务器中获取
*/
@ResponseBody
@RequestMapping(value = "userId", method = RequestMethod.GET)
public Map userId(@RequestParam("accessToken") String accessToken) {
String userName = userUtil.getUserId(accessToken);
Map<String, Object> map = new HashMap<>();
map.put("userName", userName);
return map;
}
/**
* 测试方法
*/
@ResponseBody
@RequestMapping(value = "test", method = RequestMethod.GET)
public Map<String, Object> cookieAccessToken() {
Map<String, Object> map = new HashMap<>();
map.put("value", "Success.");
return map;
}
}
package com.loit.loitcasclient.dto;
/**
* 令牌对象
*/
public class ClientAccessTokenDTO {
/**
* 令牌值
*/
private String access_token;
/**
* 令牌类型
*/
private String token_type;
/**
* 令牌过期时间(秒)
*/
private String expires_in;
/**
* 刷新令牌
*/
private String refresh_token;
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public String getToken_type() {
return token_type;
}
public void setToken_type(String token_type) {
this.token_type = token_type;
}
public String getExpires_in() {
return expires_in;
}
public void setExpires_in(String expires_in) {
this.expires_in = expires_in;
}
public String getRefresh_token() {
return refresh_token;
}
public void setRefresh_token(String refresh_token) {
this.refresh_token = refresh_token;
}
}
package com.loit.loitcasclient.dto;
public class ClientAccessTokenUserDTO {
private String id;
private Attributes attributes;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Attributes getAttributes() {
return attributes;
}
public void setAttributes(Attributes attributes) {
this.attributes = attributes;
}
private static class Attributes {
private String credentialType;
public String getCredentialType() {
return credentialType;
}
public void setCredentialType(String credentialType) {
this.credentialType = credentialType;
}
}
}
package com.loit.loitcasclient.dto;
/**
* @ClassName ClientLoitStatusCode
* @Description: 单点登录客户端状态码 编码:3位状态码中,第一位代表一个应用
* @Author gzx
* @Date 2019-10-17
* @Version V1.0
**/
public enum ClientLoitStatusCode {
SUCESS("100","成功"),
FAIL("101","失败"),
CAS_USER_TOKEN_FAIL("901", "无权限访问该资源,令牌无效或不存在"),
CAS_AUTHENTICATION_FAIL("903", "无权限访问该资源"),
;
/**
* 状态编码号
*/
public String statusCode;
/**
* 状态描述
*/
public String statusDesc;
/**
* 构造函数
* @param statusCode
* @param statusDesc
*/
ClientLoitStatusCode(String statusCode, String statusDesc){
this.statusCode = statusCode;
this.statusDesc = statusDesc;
}
}
package com.loit.loitcasclient.service;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import com.loit.loitcasclient.config.ClientAppConfig;
import com.loit.loitcasclient.utils.ClientBase64Util;
import com.loit.loitcasclient.utils.ClientCookieUtil;
import com.loit.loitcasclient.utils.LoitLog;
@Service
public class ClientLoginService {
@Autowired
private LoitLog logger;
@Autowired(required = false)
private ClientAppConfig clientAppConfig;
/**
* 一般登录行为
*/
public void login(String url, HttpServletResponse response){
try {
// 不需要登录的页面, 直接转发
List<String> forwards = clientAppConfig.getForwards();
if(forwards!=null && forwards.size()>0 && !StringUtils.isEmpty(url)){
String _url = ClientBase64Util.decoder(url);
for (String forward : forwards) {
String path = forward.substring(0, forward.indexOf("-"));
if(_url.contains(path)){
String uri = forward.substring(forward.indexOf("-") + 1);
response.sendRedirect(uri);
logger.info("ClientLoginService login() Redirect uri:"+uri);
return;
}
}
}
// 如果没有url参数, 就使用portal门户的主页地址(表示这是给portal项目配置的)
if(StringUtils.isEmpty(url)){
url = clientAppConfig.getPortalIndexUrl();
}else{
// Demon modify by 2020-05-13: 临时修改为getWebUrl,以后删除该逻辑
url = clientAppConfig.getWebUrl() + ClientBase64Util.decoder(url);
}
logger.info("前端地址:"+url);
url = ClientBase64Util.encoder(url);
response.addCookie(ClientCookieUtil.instance("url", url, clientAppConfig.getAccessTokenCookieTimOut()));
String codeUrl = clientAppConfig.codeUrl();
logger.info("ClientLoginService login() Redirect codeUrl 登录后重定向至:"+codeUrl);
response.sendRedirect(codeUrl);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 免登陆行为
* 预登录一次服务器, 登录成功后走正常流程
*/
public void loginFree(String username, String password, HttpServletResponse response){
String loginUrl = clientAppConfig.getCasServerUrl() + "/cas/login?service="+clientAppConfig.getAppServerUrl()+"/cas/login";
/*
* 如果username和password参数不为空,则免登录
* 登录页面js会吧用户名密码填充到文本框,模拟点击登录按钮进行免登录操作。
* 登录服务器配置登录校验使用门户的login/free接口。
*/
if(!StringUtils.isEmpty(username) && !StringUtils.isEmpty(password)){
loginUrl += "&username=" + username + "&password" + password;
}
try {
logger.info("ClientLoginService loginFree() Redirect loginUrl:"+loginUrl);
response.sendRedirect(loginUrl);
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.loit.loitcasclient.utils;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.loit.loitcasclient.dto.ClientLoitStatusCode;
import java.io.Serializable;
import java.util.LinkedHashMap;
/**
* $.ajax后需要接受的JSON
*
* @author
*
*/
public class ClientAjaxJson implements Serializable{
private static final long serialVersionUID = -7790919285662399570L;
public static final String CODE_COMMON_FAIL = ClientLoitStatusCode.FAIL.statusCode;
private boolean success = true;// 是否成功
private String code = ClientLoitStatusCode.SUCESS.statusCode;//返回码 100-成功,101失败,其他返回码参见LoitStatusCode
private String msg = "操作成功";// 提示信息
private LinkedHashMap<String, Object> body = new LinkedHashMap<String, Object>();//封装json的map
public LinkedHashMap<String, Object> getBody() {
return body;
}
public void setBody(LinkedHashMap<String, Object> body) {
this.body = body;
}
public void put(String key, Object value){//向json中添加属性,在js中访问,请调用data.map.key
body.put(key, value);
}
public void remove(String key){
body.remove(key);
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {//向json中添加属性,在js中访问,请调用data.msg
this.msg = msg;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
@JsonIgnore//返回对象时忽略此属性
public String getJsonStr() {//返回json字符串数组,将访问msg和key的方式统一化,都使用data.key的方式直接访问。
String json = ClientJsonMapper.getInstance().toJson(this);
return json;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
@Override
public String toString() {
return "AjaxJson [success=" + success + ", code=" + code + ", msg=" + msg + "]";
}
/**
* 返回普通异常信息。code=101
* @author wbh
* @date:2018年12月16日
* @param info
* @return
*/
public static ClientAjaxJson returnExceptionInfo(String info) {
ClientAjaxJson json = new ClientAjaxJson();
json.setSuccess(false);
json.setCode(CODE_COMMON_FAIL);
json.setMsg(info);
return json;
}
/**
* 返回普通异常信息。code=101
* @author wbh
* @date:2018年12月16日
* @param info
* @return
*/
public static ClientAjaxJson returnExceptionInfo(String info, ClientAjaxJson json) {
json.setSuccess(false);
json.setCode(CODE_COMMON_FAIL);
json.setMsg(info);
return json;
}
/**
* 返回指定异常信息。
* @author wbh
* @date:2019年10月31日
* @param code 状态码
* @param info 返回信息
* @return
*/
public static ClientAjaxJson returnExceptionInfo(ClientLoitStatusCode info) {
ClientAjaxJson json = new ClientAjaxJson();
json.setSuccess(false);
json.setCode(info.statusCode);
json.setMsg(info.statusDesc);
return json;
}
/**
* 返回指定异常信息。
* @author wbh
* @date:2019年10月31日
* @param code 状态码
* @param info 返回信息
* @return
*/
public static ClientAjaxJson returnExceptionInfo(ClientLoitStatusCode info, ClientAjaxJson json) {
json.setSuccess(false);
json.setCode(info.statusCode);
json.setMsg(info.statusDesc);
return json;
}
}
package com.loit.loitcasclient.utils;
import java.io.UnsupportedEncodingException;
import java.util.Base64;
import org.springframework.util.StringUtils;
public class ClientBase64Util {
public static String decoder(String str){
if(StringUtils.isEmpty(str)){
return null;
}
Base64.Decoder decoder = Base64.getDecoder();
try {
return new String(decoder.decode(str), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
public static String encoder(String str){
if(StringUtils.isEmpty(str)){
return null;
}
Base64.Encoder encoder = Base64.getEncoder();
try {
return encoder.encodeToString(str.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
}
package com.loit.loitcasclient.utils;
import javax.servlet.http.Cookie;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
/**
* cookie 工具
*/
public class ClientCookieUtil {
/**
* 生成cookie
* @param cookieKey 键
* @param cookieValue 值
* @param cookieTimeOut 过期时间
* @return
*/
public static Cookie instance(String cookieKey, String cookieValue, Integer cookieTimeOut){
// (key,value)
Cookie cookie = new Cookie(cookieKey, cookieValue);
// 这个要设置
cookie.setPath("/");
// 这样设置,能实现两个网站共用
// cookie.setDomain(".aotori.com");
// 不设置的话,则cookies不写入硬盘,而是写在内存,只在当前页面有用,以秒为单位
cookie.setMaxAge(cookieTimeOut);
return cookie;
}
/**
* 生成cookie
* @param cookieKey 键
* @param cookieValue 值
* @param cookieTimeOut 过期时间
* @return
*/
public static Cookie instance(String cookieKey, String cookieValue, Integer cookieTimeOut, String domain){
// (key,value)
Cookie cookie = new Cookie(cookieKey, cookieValue);
// 这个要设置
cookie.setPath("/");
// 这样设置,能实现两个网站共用
cookie.setDomain("." + domain);
// 不设置的话,则cookies不写入硬盘,而是写在内存,只在当前页面有用,以秒为单位
cookie.setMaxAge(cookieTimeOut);
return cookie;
}
/**
* 根据cookie名称获取值
*/
public static String get(Cookie[] cookies, String name){
try {
if(cookies == null || cookies.length == 0){
return null;
}
for (Cookie cookie : cookies) {
if(cookie.getName().equals(name)){
return URLDecoder.decode(cookie.getValue(), "UTF-8");
}
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
}
package com.loit.loitcasclient.utils;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
import org.apache.commons.lang3.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import java.io.IOException;
import java.util.TimeZone;
/**
* 简单封装Jackson,实现JSON String<->Java Object的Mapper.
* 封装不同的输出风格, 使用不同的builder函数创建实例.
*
* @author loit
* @version 2013-11-15
*/
@SuppressWarnings("deprecation")
public class ClientJsonMapper extends ObjectMapper {
private static final long serialVersionUID = 1L;
private static Logger logger = LoggerFactory.getLogger(ClientJsonMapper.class);
private static ClientJsonMapper mapper;
public ClientJsonMapper() {
//this(Include.NON_EMPTY);
}
public ClientJsonMapper(Include include) {
// 设置输出时包含属性的风格
if (include != null) {
this.setSerializationInclusion(include);
}
// 允许单引号、允许不带引号的字段名称
this.enableSimple();
// 设置输入时忽略在JSON字符串中存在但Java对象实际没有的属性
this.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
// 空值处理为空串
this.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
@Override
public void serialize(Object value, JsonGenerator jgen,
SerializerProvider provider) throws IOException,
JsonProcessingException {
jgen.writeString("");
}
});
// 进行HTML解码。
this.registerModule(new SimpleModule().addSerializer(String.class, new JsonSerializer<String>() {
@Override
public void serialize(String value, JsonGenerator jgen,
SerializerProvider provider) throws IOException,
JsonProcessingException {
jgen.writeString(StringEscapeUtils.unescapeHtml4(value));
}
}));
// 设置时区
this.setTimeZone(TimeZone.getDefault());//getTimeZone("GMT+8:00")
}
/**
* 创建只输出非Null且非Empty(如List.isEmpty)的属性到Json字符串的Mapper,建议在外部接口中使用.
*/
public static ClientJsonMapper getInstance() {
if (mapper == null) {
mapper = new ClientJsonMapper().enableSimple();
}
return mapper;
}
/**
* 创建只输出初始值被改变的属性到Json字符串的Mapper, 最节约的存储方式,建议在内部接口中使用。
*/
public static ClientJsonMapper nonDefaultMapper() {
if (mapper == null) {
mapper = new ClientJsonMapper(Include.NON_DEFAULT);
}
return mapper;
}
/**
* Object可以是POJO,也可以是Collection或数组。
* 如果对象为Null, 返回"null".
* 如果集合为空集合, 返回"[]".
*/
public String toJson(Object object) {
try {
return this.writeValueAsString(object);
} catch (IOException e) {
logger.warn("write to json string error:" + object, e);
return null;
}
}
/**
* 反序列化POJO或简单Collection如List<String>.
* <p>
* 如果JSON字符串为Null或"null"字符串, 返回Null.
* 如果JSON字符串为"[]", 返回空集合.
* <p>
* 如需反序列化复杂Collection如List<MyBean>, 请使用fromJson(String,JavaType)
*
* @see #fromJson(String, JavaType)
*/
public <T> T fromJson(String jsonString, Class<T> clazz) {
if (StringUtils.isEmpty(jsonString)) {
return null;
}
try {
return this.readValue(jsonString, clazz);
} catch (IOException e) {
logger.warn("parse json string error:" + jsonString, e);
return null;
}
}
/**
* 反序列化复杂Collection如List<Bean>, 先使用函數createCollectionType构造类型,然后调用本函数.
*
* @see #createCollectionType(Class, Class...)
*/
@SuppressWarnings("unchecked")
public <T> T fromJson(String jsonString, JavaType javaType) {
if (StringUtils.isEmpty(jsonString)) {
return null;
}
try {
return (T) this.readValue(jsonString, javaType);
} catch (IOException e) {
logger.warn("parse json string error:" + jsonString, e);
return null;
}
}
/**
* 構造泛型的Collection Type如:
* ArrayList<MyBean>, 则调用constructCollectionType(ArrayList.class,MyBean.class)
* HashMap<String,MyBean>, 则调用(HashMap.class,String.class, MyBean.class)
*/
public JavaType createCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {
return this.getTypeFactory().constructParametricType(collectionClass, elementClasses);
}
/**
* 當JSON裡只含有Bean的部分屬性時,更新一個已存在Bean,只覆蓋該部分的屬性.
*/
@SuppressWarnings("unchecked")
public <T> T update(String jsonString, T object) {
try {
return (T) this.readerForUpdating(object).readValue(jsonString);
} catch (JsonProcessingException e) {
logger.warn("update json string:" + jsonString + " to object:" + object + " error.", e);
} catch (IOException e) {
logger.warn("update json string:" + jsonString + " to object:" + object + " error.", e);
}
return null;
}
/**
* 輸出JSONP格式數據.
*/
public String toJsonP(String functionName, Object object) {
return toJson(new JSONPObject(functionName, object));
}
/**
* 設定是否使用Enum的toString函數來讀寫Enum,
* 為False時時使用Enum的name()函數來讀寫Enum, 默認為False.
* 注意本函數一定要在Mapper創建後, 所有的讀寫動作之前調用.
*/
public ClientJsonMapper enableEnumUseToString() {
this.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
this.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
return this;
}
/**
* 支持使用Jaxb的Annotation,使得POJO上的annotation不用与Jackson耦合。
* 默认会先查找jaxb的annotation,如果找不到再找jackson的。
*/
public ClientJsonMapper enableJaxbAnnotation() {
JaxbAnnotationModule module = new JaxbAnnotationModule();
this.registerModule(module);
return this;
}
/**
* 允许单引号
* 允许不带引号的字段名称
*/
public ClientJsonMapper enableSimple() {
this.configure(Feature.ALLOW_SINGLE_QUOTES, true);
this.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
return this;
}
/**
* 取出Mapper做进一步的设置或使用其他序列化API.
*/
public ObjectMapper getMapper() {
return this;
}
/**
* 对象转换为JSON字符串
*
* @param object
* @return
*/
public static String toJsonString(Object object) {
return ClientJsonMapper.getInstance().toJson(object);
}
/**
* JSON字符串转换为对象
*
* @param jsonString
* @param clazz
* @return
*/
public static Object fromJsonString(String jsonString, Class<?> clazz) {
return ClientJsonMapper.getInstance().fromJson(jsonString, clazz);
}
}
package com.loit.loitcasclient.utils;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.stream.Collectors;
import org.springframework.util.StringUtils;
/**
* 本地缓存工具类
*/
public class ClientLocalCacheUtil {
/**
* 缓存
*/
private static Map<String, Object> cache = new HashMap<>();
/**
* 缓存产生时间
*/
private static Map<String, Long> cacheTime = new HashMap<>();
/**
* 缓存过期时间(秒)
*/
private static Map<String, Integer> cacheOutTime = new HashMap<>();
/**
* 创建定时任务每24小时清理一次缓存
*/
static{
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
refresh();
}
},0,60000*60*24);
}
/**
* 缓存刷新,清除过期数据
*/
public static void refresh(){
for (String key : cacheOutTime.keySet()) {
ClientLocalCacheUtil.get(key);
}
}
/**
* 设置缓存
*/
public static void set(String key, Object value){
ClientLocalCacheUtil.set(key, value, null);
}
/**
* 设置有过期时间的缓存
* @param outTimeSecond 过期时间秒
*/
public static void set(String key, Object value, Integer outTimeSecond){
cache.put(key, value);
cacheTime.put(key, (new Date()).getTime());
cacheOutTime.put(key, null);
if(null != outTimeSecond){
cacheOutTime.put(key, outTimeSecond);
}
}
/**
* 获取缓存
*/
public static Object get(String key){
Integer outTime = cacheOutTime.get(key);
if(outTime != null) {
Long time = cacheTime.get(key);
if(null == time) {
return null;
}
time = cacheTime.get(key)/1000;
Long currTime = (new Date()).getTime()/1000;
// 超期了, 清除缓存
if(currTime - time >= outTime){
cache.remove(key);
cacheTime.remove(key);
cacheOutTime.remove(key);
return null;
}
}
return cache.get(key);
}
/**
* 根据key的前缀获取keys列表
* @param prefix key前缀
* @return keys列表
*/
public static List<String> keys(String prefix){
Set<String> keys = cache.keySet();
return keys.stream().filter(e -> e.startsWith(prefix)).distinct().collect(Collectors.toList());
}
/**
* 根据keys列表获取值列表
* @param keys
* @return
*/
public static List<String> values(List<String> keys){
if(StringUtils.isEmpty(keys)){
return null;
}
List<String> values = new ArrayList<>();
for (String key : keys) {
values.add((String)get(key));
}
return values;
}
}
package com.loit.loitcasclient.utils;
import com.loit.loitcasclient.dto.ClientAccessTokenDTO;
import com.loit.loitcasclient.dto.ClientAccessTokenUserDTO;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
/**
* 令牌工具类
*/
public class ClientTokenUtil {
/**
* 根据code获取登录服务器上的accessToken
* @return accessToken
* {
* "access_token": "AT-6-cRCq3wj9BBvDPj7V0dON6-m7hAB0vWgY",
* "token_type": "bearer",
* "expires_in": 28800,
* "refresh_token": "RT-6-LGG-eRoW-QNDDsfaHWF7LvrpQIDPlHoN"
* }
*/
public static String accessToken(String url, RestTemplate restTemplate){
try {
ResponseEntity<ClientAccessTokenDTO> accessTokenEntity = restTemplate.postForEntity(url, null, ClientAccessTokenDTO.class);
ClientAccessTokenDTO accessTokenDTO = accessTokenEntity.getBody();
return accessTokenDTO.getAccess_token();
} catch (RestClientException e) {
return null;
}
}
/**
* 根据accessToken获取userId
*/
public static String profile(String url, RestTemplate restTemplate){
try {
ResponseEntity<ClientAccessTokenUserDTO> userEntity = restTemplate.getForEntity(url, ClientAccessTokenUserDTO.class);
ClientAccessTokenUserDTO accessTokenUserDTO = userEntity.getBody();
return accessTokenUserDTO.getId();
} catch (RestClientException e) {
return null;
}
}
/**
* 从第三方应用的cookie中获取令牌
*/
public static String cookieAccessToken(){
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = servletRequestAttributes.getRequest();
// 从cookie中获取令牌
String accessToken = ClientCookieUtil.get(request.getCookies(), "accessToken");
return accessToken;
}
}
package com.loit.loitcasclient.utils;
import com.loit.loitcasclient.config.ClientAppConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
@Component("clientUserUtil")
public class ClientUserUtil {
@Autowired
private RestTemplate restTemplate;
@Autowired(required = false)
private ClientAppConfig clientAppConfig;
/**
* 获取登录用户id-从缓存中获取
* @param accessToken
* @return
*/
public String getUserId(String accessToken){
if(StringUtils.isEmpty(accessToken)){
return null;
}
// 从缓存获取userId, 如果没有则从登录服务器获取userId, 然后存入缓存
Object o = ClientLocalCacheUtil.get(accessToken);
if(null != o && !String.valueOf(o).equals("")){
return String.valueOf(o);
}
String userId = getCasServerUserId(accessToken);
return userId;
}
/**
* 获取登录用户id-从登录服务器获取
*/
public String getCasServerUserId(String accessToken){
String userId = ClientTokenUtil.profile(clientAppConfig.profileUrl().replace("{accessToken}", accessToken), restTemplate);
return userId;
}
}
package com.loit.loitcasclient.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class LoitLog {
protected Logger logger = LoggerFactory.getLogger(getClass());
@Value("${loit.login_debug_out:}")
private Boolean loginDebugOut;
public void info(String info) {
if(loginDebugOut!=null&&loginDebugOut)
logger.info("loginDebug "+info);
}
public Boolean getLoginDebugOut() {
return loginDebugOut;
}
public void setLoginDebugOut(Boolean loginDebugOut) {
this.loginDebugOut = loginDebugOut;
}
}
<?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">
<parent>
<artifactId>loit-core</artifactId>
<groupId>com.loit</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>loit-core-cloud</artifactId>
</project>
\ No newline at end of file
<?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">
<parent>
<artifactId>loit-core</artifactId>
<groupId>com.loit</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>loit-core-common</artifactId>
</project>
\ No newline at end of file
package com.loit.common.constant;
/**
* 缓存-常量类
* Demon add by 2020-05-21
*/
public interface CacheConstants {
/**
* rest接口:access_token -> userid
* Demon add by 2020-05-19
*/
String ACCESS_TOKEN_TO_USERID = "accesstoken:{accessToken}:to:userid";
}
package com.loit.common.constant;
/**
* 请求头常量
*
* @author wbh
* add by 2020-05-19
*/
public interface LoitHeaderConstant {
/**
* cookie中存储的token名称
*/
String TOKEN_NAME = "accessToken";
/**
* 令牌过期时间(秒)
*/
String TOKEN_NAME_OUTTIME = "accessTokenOutTime";
/**
* 用户信息,目前指userId
*/
String AUTHORIZATION = "Authorization";
}
package com.loit.common.constant;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 分页相关参数
* @author wbh12
* @date: 2020年6月6日
* add by wbh
*/
public enum LoitPageParamEnum {
PAGE_NO("pageNo", "当前页码"),
PAGE_SIZE("pageSize", "页面大小"),
REGARE("repage", "页面刷新"),
ORDER_BY("orderBy", "查询排序");
;
/**
* 状态值
*/
public String code;
/**
* 状态描述
*/
public String desc;
/**
* 构造函数
* @param code
* @param value
*/
LoitPageParamEnum(String code,String desc){
this.code = code;
this.desc = desc;
}
public static List<String> toList() {
List<String> list = new ArrayList<String>();
for (LoitPageParamEnum lppEnum : LoitPageParamEnum.values()) {
list.add(lppEnum.getCode());
}
return list;
}
public String getCode() {
return code;
}
public String getDesc() {
return desc;
}
}
<?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">
<parent>
<artifactId>loit-core</artifactId>
<groupId>com.loit</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>loit-core-tools</artifactId>
</project>
\ No newline at end of file
<?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">
<parent>
<artifactId>demo</artifactId>
<groupId>com.loit</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>loit-core</artifactId>
<version>1.0.0</version>
<modules>
<module>loit-core-cas</module>
<module>loit-core-cloud</module>
<module>loit-core-common</module>
<module>loit-core-tools</module>
</modules>
<packaging>pom</packaging>
</project>
\ No newline at end of file
......@@ -8,6 +8,7 @@
<module>loit-core-boot</module>
<module>loit-service</module>
<module>loit-service-api</module>
<module>loit-core</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论