Commit a0a51905 authored by trumansdo's avatar trumansdo
Browse files

1. 确定通用管理页面组件完成,通用组件中无法通用部分:下拉选择器;改为自定义插槽中自行添加

2. 更新element-ui版本 至2.13.0
3. 修复jwt 没有刷新过期时间。最终设置为10分钟过期时间窗口,以最后一次网络请求时间开始计算
parent 31fc8a95
package com.ibeetl.admin.console.util; package com.ibeetl.admin.console.util;
import cn.hutool.core.annotation.AnnotationUtil; import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapBuilder; import cn.hutool.core.map.MapBuilder;
import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.MapUtil;
import com.ibeetl.admin.core.annotation.ElColumn; import com.ibeetl.admin.core.annotation.ElColumn;
import com.ibeetl.admin.core.entity.CoreDict;
import com.ibeetl.admin.core.entity.ElCascaderData;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
...@@ -15,6 +20,12 @@ import java.util.Optional; ...@@ -15,6 +20,12 @@ import java.util.Optional;
*/ */
public class VOUtil { public class VOUtil {
/**
* Method resolveElColumn ... todo 预计重新定义一个类用来转换,而不是用map
*
* @param cls of type Class ,一个专门存放元数据的ElQuery类
* @return Map
*/
public static Map resolveElColumn(Class cls) { public static Map resolveElColumn(Class cls) {
MapBuilder<String, Map> mapBuilder = MapUtil.<String, Map>builder(); MapBuilder<String, Map> mapBuilder = MapUtil.<String, Map>builder();
...@@ -24,14 +35,9 @@ public class VOUtil { ...@@ -24,14 +35,9 @@ public class VOUtil {
AnnotationUtil.getAnnotationValueMap(field, ElColumn.class); AnnotationUtil.getAnnotationValueMap(field, ElColumn.class);
ElColumn elColumn = AnnotationUtil.getAnnotation(field, ElColumn.class); ElColumn elColumn = AnnotationUtil.getAnnotation(field, ElColumn.class);
Optional.ofNullable(elColumn) Optional.ofNullable(elColumn)
.ifPresent( .ifPresent(column -> mapBuilder.put(field.getName(), annotationValueMap));
column -> {
if (column.visible()) {
annotationValueMap.remove("visible");
mapBuilder.put(field.getName(), annotationValueMap);
}
});
} }
return mapBuilder.build(); return mapBuilder.build();
} }
} }
package com.ibeetl.admin.console.web; package com.ibeetl.admin.console.web;
import com.ibeetl.admin.console.util.VOUtil; import com.ibeetl.admin.console.util.VOUtil;
import com.ibeetl.admin.console.web.query.CoreUserElQuery;
import com.ibeetl.admin.core.entity.CoreUser; import com.ibeetl.admin.core.entity.CoreUser;
import com.ibeetl.admin.core.service.CoreUserService; import com.ibeetl.admin.core.service.CoreUserService;
import com.ibeetl.admin.core.web.JsonResult; import com.ibeetl.admin.core.web.JsonResult;
...@@ -14,13 +15,13 @@ import org.springframework.web.bind.annotation.RestController; ...@@ -14,13 +15,13 @@ import org.springframework.web.bind.annotation.RestController;
@Validated @Validated
@RestController @RestController
public class UserElController { public class CoreUserElController {
@Autowired private CoreUserService coreUserService; @Autowired private CoreUserService coreUserService;
@GetMapping("/users/metedata") @GetMapping("/users/metadata")
public JsonResult<Map> usersMetedata() { public JsonResult<Map> usersMetedata() {
return JsonResult.success(VOUtil.resolveElColumn(CoreUser.class)); return JsonResult.success(VOUtil.resolveElColumn(CoreUserElQuery.class));
} }
@GetMapping("/users") @GetMapping("/users")
......
package com.ibeetl.admin.console.web.query;
import static com.ibeetl.admin.core.util.enums.ElColumnType.DATE;
import static com.ibeetl.admin.core.util.enums.ElColumnType.DICT;
import static com.ibeetl.admin.core.util.enums.ElColumnType.STRING;
import com.ibeetl.admin.core.annotation.ElColumn;
import java.util.Date;
import lombok.Data;
/**
* Class CoreUserElQuery : <br>
* 描述:用户管理页面的metadata元数据
*
* @author 一日看尽长安花 Created on 2019/12/29
*/
@Data
public class CoreUserElQuery {
@ElColumn(name = "ID", type = STRING)
protected Long id;
@ElColumn(name = "创建时间", type = DATE)
protected Date createTime;
@ElColumn(name = "用户名", type = STRING)
private String code;
@ElColumn(name = "姓名", type = STRING)
private String name;
@ElColumn(name = "状态", type = STRING)
private String state;
@ElColumn(name = "职务", type = DICT)
private String jobType0;
@ElColumn(name = "岗位", type = DICT)
private String jobType1;
}
...@@ -15,29 +15,35 @@ import java.lang.annotation.Target; ...@@ -15,29 +15,35 @@ import java.lang.annotation.Target;
public @interface ElColumn { public @interface ElColumn {
/** /**
* 数据表格中的列名称 * 数据表格列头显示名称
* @return * @return
* */ * */
String name(); String name();
/** /**
* 该列的类型。{@link com.ibeetl.admin.core.util.enums.ElColumnType} * 该列的类型。查看 {@link com.ibeetl.admin.core.util.enums.ElColumnType}
* @return * @return
* */ * */
String type(); String type();
/** /**
* 增加数据表格的手动排序 * 开启element-ui 中数据表格的手动排序
* @return * @return
* */ * */
boolean sortable() default false; boolean sortable() default false;
/** /**
* 是否在前端页面可见,本质是在后端过滤掉注解的字段 * 是否在前端页面的查询条件区显示
* @return * @return
* */ * */
boolean visible() default true; boolean visible() default true;
/**
* 是否在前端页面的数据表格列中显示
* @return
* */
boolean displayable() default true;
/** /**
* 是否在表单中是必填。暂时没做规则的生成功能,暂定没有 * 是否在表单中是必填。暂时没做规则的生成功能,暂定没有
* @return * @return
......
...@@ -48,11 +48,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; ...@@ -48,11 +48,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor; import org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
/** /** 切勿在此配置类中向SpringMVC中添加bean。 也就是不要 @Bean这类方法。 会出现无法ServletContext注入null,因为父接口的原因 */
* 切勿在此配置类中向SpringMVC中添加bean。
* 也就是不要 @Bean这类方法。
* 会出现无法ServletContext注入null,因为父接口的原因
* */
@Configuration @Configuration
public class SpringWebMvcConfigurer implements WebMvcConfigurer, InitializingBean { public class SpringWebMvcConfigurer implements WebMvcConfigurer, InitializingBean {
...@@ -81,8 +77,11 @@ public class SpringWebMvcConfigurer implements WebMvcConfigurer, InitializingBea ...@@ -81,8 +77,11 @@ public class SpringWebMvcConfigurer implements WebMvcConfigurer, InitializingBea
*/ */
@Override @Override
public void addInterceptors(InterceptorRegistry registry) { public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new SessionInterceptor(userService)).addPathPatterns("/**"); registry.addInterceptor(new HttpRequestInterceptor()).addPathPatterns("/**");
// super.addInterceptors(registry); registry
.addInterceptor(new SessionInterceptor(userService))
.excludePathPatterns("/user/login", "/error", "/user/logout")
.addPathPatterns("/**");
} }
/** /**
...@@ -124,6 +123,22 @@ public class SpringWebMvcConfigurer implements WebMvcConfigurer, InitializingBea ...@@ -124,6 +123,22 @@ public class SpringWebMvcConfigurer implements WebMvcConfigurer, InitializingBea
} }
} }
class HttpRequestInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(
HttpServletRequest request, HttpServletResponse response, Object handler) {
HttpRequestLocal.set(request);
return true;
}
@Override
public void afterCompletion(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
HttpRequestLocal.destory();
}
}
class SessionInterceptor implements HandlerInterceptor { class SessionInterceptor implements HandlerInterceptor {
CoreUserService userService; CoreUserService userService;
...@@ -135,38 +150,20 @@ class SessionInterceptor implements HandlerInterceptor { ...@@ -135,38 +150,20 @@ class SessionInterceptor implements HandlerInterceptor {
@Override @Override
public boolean preHandle( public boolean preHandle(
HttpServletRequest request, HttpServletResponse response, Object handler) { HttpServletRequest request, HttpServletResponse response, Object handler) {
HttpRequestLocal.set(request);
if (StrUtil.containsAny(request.getRequestURI(), "/login", "/error", "/logout")) {
return true;
}
String token = HttpRequestLocal.getAuthorization(); String token = HttpRequestLocal.getAuthorization();
Map<String, Object> payload = JoseJwtUtil.parsePayload(token); boolean isExpiration = JoseJwtUtil.verifyJwtJson(token);
if (payload.isEmpty()) { if (isExpiration) {
/*验证失败,无效jwt*/ /*验证失败,无效jwt*/
return false; return false;
} else {
token = JoseJwtUtil.refreshIssuedAtTime(token);
response.setHeader(HttpHeaders.AUTHORIZATION, token);
} }
return true; return true;
} }
@Override
public void postHandle(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) {
/* do nothing */
}
@Override
public void afterCompletion(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
/* do nothing */
}
} }
/** 自定义SpringMVC的controller参数注解 {@link RequestBodyPlus} 的注入解析,用json path 的方式注入json请求的参数 */ /** 自定义SpringMVC的controller方法的参数注解 {@link RequestBodyPlus} 的注入解析, 用json path 的方式注入json请求的参数 */
class RequestBodyPlusProcessor extends AbstractMessageConverterMethodProcessor { class RequestBodyPlusProcessor extends AbstractMessageConverterMethodProcessor {
private static final ThreadLocal<String> bodyLocal = ThreadLocal.withInitial(() -> "{}"); private static final ThreadLocal<String> bodyLocal = ThreadLocal.withInitial(() -> "{}");
......
...@@ -25,24 +25,20 @@ public class CoreUser extends BaseEntity { ...@@ -25,24 +25,20 @@ public class CoreUser extends BaseEntity {
@NotNull(message = "ID不能为空", groups = ValidateConfig.UPDATE.class) @NotNull(message = "ID不能为空", groups = ValidateConfig.UPDATE.class)
@SeqID(name = ORACLE_CORE_SEQ_NAME) @SeqID(name = ORACLE_CORE_SEQ_NAME)
@ElColumn(name = "ID", type = ElColumnType.STRING)
@AutoID @AutoID
protected Long id; protected Long id;
// 删除标识 // 删除标识
@JsonIgnore protected Integer delFlag = 0; @JsonIgnore protected Integer delFlag = 0;
// 创建时间 // 创建时间
@ElColumn(name = "创建时间", type = ElColumnType.DATE)
protected Date createTime; protected Date createTime;
// 登录名,编号 // 登录名,编号
@NotBlank(message = "用户编号不能为空", groups = ValidateConfig.ADD.class) @NotBlank(message = "用户编号不能为空", groups = ValidateConfig.ADD.class)
@Null(message = "用户编号不能为空", groups = ValidateConfig.UPDATE.class) @Null(message = "用户编号不能为空", groups = ValidateConfig.UPDATE.class)
@ElColumn(name = "用户名", type = ElColumnType.STRING)
private String code; private String code;
// 用户姓名 // 用户姓名
@NotBlank(message = "用户名不能为空") @NotBlank(message = "用户名不能为空")
@ElColumn(name = "姓名", type = ElColumnType.STRING)
private String name; private String name;
// 组织机构id // 组织机构id
...@@ -53,16 +49,13 @@ public class CoreUser extends BaseEntity { ...@@ -53,16 +49,13 @@ public class CoreUser extends BaseEntity {
@JsonIgnore private String password; @JsonIgnore private String password;
@Dict(type = CoreDictType.USER_STATE) @Dict(type = CoreDictType.USER_STATE)
@ElColumn(name = "状态", type = ElColumnType.STRING)
private String state; private String state;
// 扩展例子 // 扩展例子
@Dict(type = "job_type") @Dict(type = "job_type")
@ElColumn(name = "职位", type = ElColumnType.DICT)
private DictType jobType0; private DictType jobType0;
@Dict(type = "job_type") @Dict(type = "job_type")
@ElColumn(name = "职位", type = ElColumnType.DICT)
private DictType jobType1; private DictType jobType1;
private Date updateTime; private Date updateTime;
......
...@@ -4,10 +4,9 @@ import lombok.Data; ...@@ -4,10 +4,9 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
/** /**
* 专门用于前端UI下拉选择器的字典数据返回类型,与{@link CoreDict} 不同,它是业务中的类。 * 用于数据表格的显示<br/>
* 用于数据库表的字典字段映射到本对象中的value字段<br>
* pojo中字典字段必须使用该类定义<br> * pojo中字典字段必须使用该类定义<br>
* 处理最终的字典值由{@link com.ibeetl.admin.core.service.CoreBaseService#processDictField} 方法提供<br/> * 由{@link com.ibeetl.admin.core.service.CoreBaseService#processDictField} 方法转换<br/>
*/ */
@Data @Data
@NoArgsConstructor @NoArgsConstructor
......
package com.ibeetl.admin.core.entity;
import lombok.Data;
import lombok.NoArgsConstructor;
/** 前端级联器的数据格式类 */
@Data
@NoArgsConstructor
public class ElCascaderData {
private Long id;
private String label;
private String value;
}
package com.ibeetl.admin.core.service; package com.ibeetl.admin.core.service;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.ibeetl.admin.core.dao.SQLManagerBaseDao; import com.ibeetl.admin.core.dao.SQLManagerBaseDao;
import com.ibeetl.admin.core.entity.DictType; import com.ibeetl.admin.core.entity.DictType;
import com.ibeetl.admin.core.util.AnnotationUtil; import com.ibeetl.admin.core.util.cache.DictTypeCacheUtil;
import com.ibeetl.admin.core.util.FileDownloadUtil;
import com.ibeetl.admin.core.util.cache.DictCacheUtil;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.util.ArrayList; import java.util.ArrayList;
...@@ -22,8 +13,6 @@ import java.util.HashMap; ...@@ -22,8 +13,6 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import org.beetl.sql.core.SQLManager;
import org.beetl.sql.core.TailBean; import org.beetl.sql.core.TailBean;
import org.beetl.sql.core.engine.PageQuery; import org.beetl.sql.core.engine.PageQuery;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
...@@ -32,7 +21,6 @@ import com.ibeetl.admin.core.annotation.Dict; ...@@ -32,7 +21,6 @@ import com.ibeetl.admin.core.annotation.Dict;
import com.ibeetl.admin.core.entity.CoreDict; import com.ibeetl.admin.core.entity.CoreDict;
import com.ibeetl.admin.core.util.PlatformException; import com.ibeetl.admin.core.util.PlatformException;
import com.ibeetl.admin.core.util.enums.DelFlagEnum; import com.ibeetl.admin.core.util.enums.DelFlagEnum;
import org.springframework.beans.factory.annotation.Qualifier;
/** /**
* 描述: * 描述:
...@@ -213,12 +201,12 @@ public class CoreBaseService<T> { ...@@ -213,12 +201,12 @@ public class CoreBaseService<T> {
} }
public void processObjectsDictField(PageQuery pageQuery){ public void processObjectsDictField(PageQuery pageQuery){
processObjectsDictField(pageQuery.getList()); this.processObjectsDictField(pageQuery.getList());
} }
public void processObjectsDictField(Collection collection){ public void processObjectsDictField(Collection collection){
for (Object o : collection) { for (Object o : collection) {
processDictField(o); this.processDictField(o);
} }
} }
...@@ -236,7 +224,7 @@ public class CoreBaseService<T> { ...@@ -236,7 +224,7 @@ public class CoreBaseService<T> {
continue; continue;
} }
DictType key = new DictType(type, dictType.getValue()); DictType key = new DictType(type, dictType.getValue());
dictType = DictCacheUtil.get(key); dictType = DictTypeCacheUtil.get(key);
ReflectUtil.setFieldValue(object, field, dictType); ReflectUtil.setFieldValue(object, field, dictType);
} }
} }
......
package com.ibeetl.admin.core.service; package com.ibeetl.admin.core.service;
import cn.hutool.core.util.StrUtil;
import com.ibeetl.admin.core.web.JsonResult;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.beetl.sql.core.mapper.internal.LambdaQueryAmi;
import org.beetl.sql.core.query.LambdaQuery;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
...@@ -24,8 +28,6 @@ import com.ibeetl.admin.core.util.enums.DelFlagEnum; ...@@ -24,8 +28,6 @@ import com.ibeetl.admin.core.util.enums.DelFlagEnum;
@Transactional @Transactional
public class CoreDictService extends CoreBaseService<CoreDict> { public class CoreDictService extends CoreBaseService<CoreDict> {
private static final Logger LOGGER = LoggerFactory.getLogger(CoreDictService.class);
@Autowired private CoreDictDao dictDao; @Autowired private CoreDictDao dictDao;
@Autowired CorePlatformService platformService; @Autowired CorePlatformService platformService;
...@@ -57,14 +59,27 @@ public class CoreDictService extends CoreBaseService<CoreDict> { ...@@ -57,14 +59,27 @@ public class CoreDictService extends CoreBaseService<CoreDict> {
} }
/** /**
* 级联字段下一级的字段列表 * Method findChildByParent ...<br>
* 获取某类型或者某个父级下的字典列表,参数二选一即可,也可都有。不可都不存在 <br>
* *
* @param id : 父级的 parentValue * @param parentId of type Long 父级id
* @return * @param type of type String 字典type
* @return List<CoreDict>
*/ */
@Cacheable(value = CorePlatformService.DICT_CACHE_CHILDREN) @Cacheable(value = CorePlatformService.DICT_CACHE_CHILDREN)
public List<CoreDict> findChildByParent(Long id) { public List<CoreDict> findChildByParent(Long parentId, String type) {
return dictDao.findChildByParent(id); if (StrUtil.isBlank(type) && parentId == null) {
return null;
}
LambdaQuery<CoreDict> lambdaQuery = dictDao.getSQLManager().lambdaQuery(CoreDict.class);
if (parentId != null) {
lambdaQuery.andEq(CoreDict::getParent, parentId);
}
if (StrUtil.isNotBlank(type)) {
lambdaQuery.andEq(CoreDict::getType, type);
}
List<CoreDict> coreDictList = lambdaQuery.orderBy(CoreDict::getSort).select();
return coreDictList;
} }
@Cacheable(value = CorePlatformService.DICT_CACHE_VALUE) @Cacheable(value = CorePlatformService.DICT_CACHE_VALUE)
...@@ -98,7 +113,7 @@ public class CoreDictService extends CoreBaseService<CoreDict> { ...@@ -98,7 +113,7 @@ public class CoreDictService extends CoreBaseService<CoreDict> {
if (dict.getValue().equals(value)) { if (dict.getValue().equals(value)) {
return list; return list;
} else { } else {
List<CoreDict> children = findChildByParent(dict.getId()); List<CoreDict> children = findChildByParent(dict.getId(), null);
if (children.isEmpty()) { if (children.isEmpty()) {
continue; continue;
} else { } else {
......
...@@ -76,7 +76,7 @@ public class CoreUserService extends CoreBaseService { ...@@ -76,7 +76,7 @@ public class CoreUserService extends CoreBaseService {
.getSQLManager() .getSQLManager()
.lambdaQuery(CoreUser.class) .lambdaQuery(CoreUser.class)
.page(page, limit); .page(page, limit);
processObjectsDictField(pageQuery); super.processObjectsDictField(pageQuery);
return pageQuery; return pageQuery;
} }
......
package com.ibeetl.admin.core.service;
import com.ibeetl.admin.core.dao.CoreDictDao;
import com.ibeetl.admin.core.entity.DictType;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class DictTypeService {
@Autowired private CoreDictDao dictDao;
public List<DictType> findAllList(String type) {
return dictDao.findAllDictType(type);
}
}
...@@ -75,6 +75,10 @@ public final class HttpRequestLocal { ...@@ -75,6 +75,10 @@ public final class HttpRequestLocal {
getHttpSession().removeAttribute(ACCESS_USER_ORGS); getHttpSession().removeAttribute(ACCESS_USER_ORGS);
} }
public static void destory() {
requests.remove();
}
public static Cookie getCookieByName(String cookieName) { public static Cookie getCookieByName(String cookieName) {
Assert.notNull(cookieName); Assert.notNull(cookieName);
Cookie[] cookies = get().getCookies(); Cookie[] cookies = get().getCookies();
......
...@@ -16,28 +16,125 @@ import org.slf4j.Logger; ...@@ -16,28 +16,125 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* 基于jose4j的jwt库工具类。 包括:生成,验证,解析负载。<br/> * 基于jose4j的jwt库工具类。 包括:生成,验证,解析负载。<br>
* 可以用对称加密算法在此对token进行加密,逻辑上可以每隔一周或者一天,动态生成对称加密算法的密钥,然后防止破解。<br/> * 可以用对称加密算法在此对token进行加密,逻辑上可以每隔一周或者一天,动态生成对称加密算法的密钥,然后防止破解。<br>
* 这样可以用jwt来承担更多的数据传递。至于客官怎么选择——萝卜青菜各有所爱<br/> * 这样可以用jwt来承担更多的数据传递。至于客官怎么选择——萝卜青菜各有所爱<br>
* iss: jwt签发者 sub: jwt所面向的用户 aud: 接收jwt的一方 exp: jwt的过期时间,这个过期时间必须要大于签发时间 nbf: 定义在什么时间之前,该jwt都是不可用的.
* iat: jwt的签发时间 jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
* *
* @author 一日看尽长安花 * @author 一日看尽长安花
*/ */
public class JoseJwtUtil { public class JoseJwtUtil {
private static Logger logger = LoggerFactory.getLogger(JoseJwtUtil.class); private static Logger logger = LoggerFactory.getLogger(JoseJwtUtil.class);
private static int EXPIRATION_TIME = 10;
/**
* Method generateJwtToken ... <br>
* 生成jwt token字符串
*
* @param uid of type String
* @return String
*/
public static String generateJwtToken(String uid) {
JwtClaims jwtClaims = JoseJwtUtil.getJwtClaims(uid);
JsonWebSignature jsonWebSignature = JoseJwtUtil.getJsonWebSignature(jwtClaims);
String jwt = "invalid jwt";
try {
jwt = jsonWebSignature.getCompactSerialization();
} catch (JoseException e) {
logger.error(
"can't generate jwt of {} user.: detail see next follow: \n {} ",
uid,
e.getLocalizedMessage());
}
return jwt;
}
public static String generateJwtJson(String uid) { /**
* Method verifyJwtJson ... <br>
* 验证jwt是否过期<br>
*
* @param token of type String
* @return boolean
*/
public static boolean verifyJwtJson(String token) {
return JoseJwtUtil.parsePayload(token).isEmpty();
}
/**
* Method refreshIssuedAtTime ...<br>
* 刷新颁发时间,达到重置30分钟时间验证窗口
*
* @param token of type String
* @return String
*/
public static String refreshIssuedAtTime(String token) {
JwtConsumer jwtConsumer = JoseJwtUtil.getJwtConsumer(token);
JwtClaims jwtClaims = null;
String jwt = "invalid jwt";
try {
jwtClaims = jwtConsumer.processToClaims(token);
jwtClaims.setIssuedAtToNow();
jwtClaims.setExpirationTimeMinutesInTheFuture(EXPIRATION_TIME);
JsonWebSignature jsonWebSignature = JoseJwtUtil.getJsonWebSignature(jwtClaims);
jwt = jsonWebSignature.getCompactSerialization();
} catch (InvalidJwtException e) {
logger.error("parser token fail.detail see next follow: {} ", e.getLocalizedMessage());
} catch (JoseException e) {
logger.error("can't refresh jwt : detail see next follow: \n {} ", e.getLocalizedMessage());
}
return jwt;
}
/**
* Method parsePayload ... 解析请求中的jwt token,返回map是为了避免业务中使用jose的类。 若有必要可以自定义一个类
*
* @param token of type String
* @return Map<String, Object>
*/
public static Map<String, Object> parsePayload(String token) {
JwtConsumer jwtConsumer = JoseJwtUtil.getJwtConsumer(token);
Map<String, Object> claimsMap = MapUtil.newHashMap(0);
try {
JwtClaims jwtClaims = jwtConsumer.processToClaims(token);
claimsMap = jwtClaims.getClaimsMap();
} catch (InvalidJwtException e) {
logger.error("parser token fail.detail see next follow: {} ", e.getLocalizedMessage());
}
return claimsMap;
}
public static JsonWebSignature getJsonWebSignature(JwtClaims jwtClaims) {
RsaJsonWebKey rsaJsonWebKey = RsaJsonWebKeyBuilder.getRasJsonWebKeyInstance();
JsonWebSignature jsonWebSignature = new JsonWebSignature();
jsonWebSignature.setPayload(jwtClaims.toJson());
jsonWebSignature.setKey(rsaJsonWebKey.getPrivateKey());
jsonWebSignature.setKeyIdHeaderValue(rsaJsonWebKey.getKeyId());
jsonWebSignature.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
return jsonWebSignature;
}
/**
* Method getJwtClaims ... <br>
* 获取jwt 签名类 <br>
* 包含了登录时间,所以尽可能只用于登录的jwt<br>
*
* @param uid of type String
* @return JwtClaims
*/
public static JwtClaims getJwtClaims(String uid) {
JwtClaims jwtClaims = new JwtClaims(); JwtClaims jwtClaims = new JwtClaims();
jwtClaims.setExpirationTimeMinutesInTheFuture(30); /*设置过期时间*/
/* 以分钟为单位的过期时间 */ /* 颁发签名者 */
/* who creates the token and signs it */
jwtClaims.setIssuer("Issuer"); jwtClaims.setIssuer("Issuer");
/* to whom the token is intended to be sent */ /* 接收签名者 */
jwtClaims.setAudience("Audience"); jwtClaims.setAudience("Audience");
/* a unique identifier for the token */ /* a unique identifier for the token */
jwtClaims.setGeneratedJwtId(); jwtClaims.setGeneratedJwtId();
/* when the token was issued/created (now) */ /* when the token was issued/created (now) */
jwtClaims.setIssuedAtToNow(); jwtClaims.setIssuedAtToNow();
/* time before which the token is not yet valid (2 minutes ago) */ /* 以分钟为单位的过期时间 */
jwtClaims.setExpirationTimeMinutesInTheFuture(EXPIRATION_TIME);
/* 参照jwt规范中nbf字段。用于解决多服务中时间差问题 */
jwtClaims.setNotBeforeMinutesInThePast(2); jwtClaims.setNotBeforeMinutesInThePast(2);
/*主题:签证*/ /*主题:签证*/
jwtClaims.setSubject("Bearer"); jwtClaims.setSubject("Bearer");
...@@ -46,33 +143,21 @@ public class JoseJwtUtil { ...@@ -46,33 +143,21 @@ public class JoseJwtUtil {
/*登录时间*/ /*登录时间*/
jwtClaims.setClaim("ltm", System.currentTimeMillis()); jwtClaims.setClaim("ltm", System.currentTimeMillis());
RsaJsonWebKey rsaJsonWebKey = RsaJsonWebKeyBuilder.getRasJsonWebKeyInstance(); return jwtClaims;
JsonWebSignature jsonWebSignature = new JsonWebSignature();
jsonWebSignature.setPayload(jwtClaims.toJson());
jsonWebSignature.setKey(rsaJsonWebKey.getPrivateKey());
jsonWebSignature.setKeyIdHeaderValue(rsaJsonWebKey.getKeyId());
jsonWebSignature.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
String jwt = "invalid jwt";
try {
jwt = jsonWebSignature.getCompactSerialization();
} catch (JoseException e) {
logger.error(
"can't generate jwt of user: {}. detail see next follow: \n {} ",
uid,
e.getLocalizedMessage());
}
return jwt;
}
public static boolean verifyJwtJson(String token) {
return JoseJwtUtil.parsePayload(token).isEmpty();
} }
public static Map<String, Object> parsePayload(String token) { /**
* Method getJwtConsumer ... 获取 jwt 验证消费者
*
* @param token of type String
* @return JwtConsumer
*/
public static JwtConsumer getJwtConsumer(String token) {
JwtConsumer jwtConsumer = JwtConsumer jwtConsumer =
new JwtConsumerBuilder() new JwtConsumerBuilder()
.setRequireExpirationTime() // the JWT must have an expiration time .setRequireExpirationTime() // the JWT must have an expiration time
.setMaxFutureValidityInMinutes(30) // but the expiration time can't be too crazy .setMaxFutureValidityInMinutes(
EXPIRATION_TIME) // but the expiration time can't be too crazy
.setAllowedClockSkewInSeconds(30) // 允许校准过期时间的偏差30秒 .setAllowedClockSkewInSeconds(30) // 允许校准过期时间的偏差30秒
.setRequireSubject() // the JWT must have a subject claim .setRequireSubject() // the JWT must have a subject claim
.setExpectedIssuer("Issuer") // whom the JWT needs to have been issued by .setExpectedIssuer("Issuer") // whom the JWT needs to have been issued by
...@@ -81,16 +166,15 @@ public class JoseJwtUtil { ...@@ -81,16 +166,15 @@ public class JoseJwtUtil {
RsaJsonWebKeyBuilder.getRasJsonWebKeyInstance() RsaJsonWebKeyBuilder.getRasJsonWebKeyInstance()
.getPublicKey()) // verify the signature with the public key .getPublicKey()) // verify the signature with the public key
.build(); // create the JwtConsumer instance .build(); // create the JwtConsumer instance
Map<String, Object> claimsMap = MapUtil.newHashMap(0); return jwtConsumer;
try {
JwtClaims jwtClaims = jwtConsumer.processToClaims(token);
claimsMap = jwtClaims.getClaimsMap();
} catch (InvalidJwtException e) {
logger.error("parser token fail.detail see next follow: {} ", e.getLocalizedMessage());
}
return claimsMap;
} }
/**
* Class RsaJsonWebKeyBuilder : <br>
* 描述:线程安全
*
* @author 一日看尽长安花 Created on 2020/1/11
*/
private static class RsaJsonWebKeyBuilder { private static class RsaJsonWebKeyBuilder {
private static volatile RsaJsonWebKey rsaJsonWebKey; private static volatile RsaJsonWebKey rsaJsonWebKey;
......
...@@ -10,7 +10,13 @@ import com.ibeetl.admin.core.util.SpringUtil; ...@@ -10,7 +10,13 @@ import com.ibeetl.admin.core.util.SpringUtil;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class DictCacheUtil { /**
* Class DictTypeCacheUtil : <br/>
* 描述:{@link DictType} 类的缓存工具类,同时提供将 {@link CoreDict} 转换至 {@link DictType} 方法
* @author 一日看尽长安花
* Created on 2020/1/11
*/
public class DictTypeCacheUtil {
private static final Cache<String, Object> CACHE = private static final Cache<String, Object> CACHE =
Caffeine.newBuilder().maximumSize(1024).recordStats().build(); Caffeine.newBuilder().maximumSize(1024).recordStats().build();
...@@ -38,6 +44,12 @@ public class DictCacheUtil { ...@@ -38,6 +44,12 @@ public class DictCacheUtil {
}); });
} }
/**
* Method getKey ...
* 一个字典记录的key应该由type + value 构成
* @param dictType of type DictType
* @return String
*/
public static String getKey(DictType dictType) { public static String getKey(DictType dictType) {
return dictType.getType() + ":" + dictType.getValue(); return dictType.getType() + ":" + dictType.getValue();
} }
......
...@@ -7,7 +7,10 @@ public interface ElColumnType { ...@@ -7,7 +7,10 @@ public interface ElColumnType {
/** 前端页面输入框 */ /** 前端页面输入框 */
String STRING = "string"; String STRING = "string";
/** 前端页面下拉选择器 */ /**
* 不出现在搜索面板中,只出现在数据表格中。
* 建议下拉选择器通过级联选择器实现
* */
String DICT = "dict"; String DICT = "dict";
/** 前端页面的日期选择器 */ /** 前端页面的日期选择器 */
......
...@@ -46,7 +46,7 @@ public class CoreDictController { ...@@ -46,7 +46,7 @@ public class CoreDictController {
@ResponseBody @ResponseBody
public JsonResult<List<CoreDict>> viewChild(String group, String value) { public JsonResult<List<CoreDict>> viewChild(String group, String value) {
CoreDict dict = dictService.findCoreDict(group, value); CoreDict dict = dictService.findCoreDict(group, value);
List<CoreDict> list = dictService.findChildByParent(dict.getId()); List<CoreDict> list = dictService.findChildByParent(dict.getId(), null);
return JsonResult.success(list); return JsonResult.success(list);
} }
} }
package com.ibeetl.admin.core.web; package com.ibeetl.admin.core.web;
import com.ibeetl.admin.core.annotation.RequestBodyPlus; import cn.hutool.core.util.StrUtil;
import com.ibeetl.admin.core.entity.CoreDict; import com.ibeetl.admin.core.entity.CoreDict;
import com.ibeetl.admin.core.entity.DictType; import com.ibeetl.admin.core.entity.ElCascaderData;
import com.ibeetl.admin.core.service.CoreDictService; import com.ibeetl.admin.core.service.CoreDictService;
import com.ibeetl.admin.core.service.CorePlatformService; import java.util.ArrayList;
import com.ibeetl.admin.core.service.DictTypeService;
import java.util.List; import java.util.List;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
...@@ -22,19 +20,35 @@ import org.springframework.web.bind.annotation.RestController; ...@@ -22,19 +20,35 @@ import org.springframework.web.bind.annotation.RestController;
@Slf4j @Slf4j
@RestController @RestController
@RequestMapping(value = "/core/dicts") @RequestMapping(value = "/core/dicts")
public class DictDataElController { public class DictCascaderElController {
@Autowired DictTypeService dictTypeService; @Autowired CoreDictService coreDictService;
/** /**
* 根据字典类型type,获取所有字典数据并返回 * Method obtainDcitsByCascader ... 获取子级字典列表。如果不传父级id,只获取type指定的列表而已。
* *
* @param type * @param parentId of type Long 父级id
* @return * @param type of type String 子级字典列表type
* @return JsonResult<List < ElCascaderData>>
*/ */
@GetMapping @GetMapping
public JsonResult<List<DictType>> dictList(String type) { public JsonResult<List<ElCascaderData>> obtainDcitsByCascader(Long parentId, String type) {
List<DictType> list = dictTypeService.findAllList(type); if (StrUtil.isBlank(type) && parentId == null) {
return JsonResult.success(list); return JsonResult.failMessage("parentId and type should have at least one.");
}
List<CoreDict> childDictList = coreDictService.findChildByParent(parentId, type);
return JsonResult.success(convertToCascaderData(childDictList));
}
private List<ElCascaderData> convertToCascaderData(List<CoreDict> coreDicts) {
List<ElCascaderData> cascaderDataArrayList = new ArrayList<ElCascaderData>(coreDicts.size());
for (CoreDict dict : coreDicts) {
ElCascaderData data = new ElCascaderData();
data.setId(dict.getId());
data.setLabel(dict.getName());
data.setValue(dict.getValue());
cascaderDataArrayList.add(data);
}
return cascaderDataArrayList;
} }
} }
...@@ -12,7 +12,6 @@ import com.ibeetl.admin.core.service.CoreUserService; ...@@ -12,7 +12,6 @@ import com.ibeetl.admin.core.service.CoreUserService;
import com.ibeetl.admin.core.util.HttpRequestLocal; import com.ibeetl.admin.core.util.HttpRequestLocal;
import com.ibeetl.admin.core.util.JoseJwtUtil; import com.ibeetl.admin.core.util.JoseJwtUtil;
import com.ibeetl.admin.core.util.PlatformException; import com.ibeetl.admin.core.util.PlatformException;
import com.ibeetl.admin.core.web.JsonResult;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
...@@ -21,7 +20,7 @@ import org.springframework.web.bind.annotation.PostMapping; ...@@ -21,7 +20,7 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@RestController @RestController
public class CoreUserElController { public class UserLoginElController {
@Autowired private RoleRoutesElService roleRoutesService; @Autowired private RoleRoutesElService roleRoutesService;
...@@ -67,7 +66,7 @@ public class CoreUserElController { ...@@ -67,7 +66,7 @@ public class CoreUserElController {
HttpRequestLocal.setLoginerInfo(info.getUser(), info.getCurrentOrg(), info.getOrgs()); HttpRequestLocal.setLoginerInfo(info.getUser(), info.getCurrentOrg(), info.getOrgs());
Map<String, Object> resultMap = Map<String, Object> resultMap =
MapUtil.<String, Object>builder() MapUtil.<String, Object>builder()
.put("token", JoseJwtUtil.generateJwtJson(String.valueOf(user.getId()))) .put("token", JoseJwtUtil.generateJwtToken(String.valueOf(user.getId())))
.build(); .build();
return JsonResult.success(resultMap); return JsonResult.success(resultMap);
} }
......
...@@ -32,7 +32,6 @@ findChildByParent ...@@ -32,7 +32,6 @@ findChildByParent
WHERE WHERE
parent = #id# and del_flag = 0 order by sort DESC parent = #id# and del_flag = 0 order by sort DESC
bathDelByValue bathDelByValue
=== ===
update core_dict set del_flag =1 where value in in ( #join(values)#) update core_dict set del_flag =1 where value in in ( #join(values)#)
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment