提交 be4d284c 编写于 作者: ibizdev's avatar ibizdev

ibiz4j 发布系统代码

上级 be653782
## v7.0.0-alpha.9 [2020-6-11]
### Bug修复
数值代码表多语言
树右键菜单滚动条样式bug
列表面板界面行为bug
多选视图界面逻辑修复
图表刷新bug修复
日历部件选中抛出数据逻辑调整
编辑视图,app-span显示0时不显示
树视图右键界面行为刷新bug
快捷菜单控制台报错bug
门户加载自定义模型错误时,正常显示默认看板
修复雷达图显示异常问题
修复编辑类、分页导航视图带数据标题问题
修复饼图、漏斗图 获取序列参数错误问题
### 功能新增及优化
#### 模板
看板和门户布局模板调整,支持门户部件标题栏界面行为组
支持数据选择、地址框、自动完成、下拉列表、标签、选项框列表、单选列表等编辑器导航参数调整
支持树导航栏、表格导航栏、列表导航栏、卡片导航栏、日历导航栏、表单关系界面、数据选择面板、分页导航面板、数据关系栏、界面行为、新建逻辑、编辑逻辑导航参数调整
支持图表无数据时显示暂无数据
支持表格新建默认值
支持日历部件右键菜单
支持表格列触发界面行为
面板布局调整
#### 基础文件
门户部件视图的样式
数据选择,地址框,自动完成,下拉列表,标签,选项框列表,单选列表等编辑器导航参数调整
表单项label位置
调整登录页面
穿梭框编辑器支持
## v7.0.0-alpha.8 [2020-6-4]
### Bug修复
......
......@@ -16,4 +16,31 @@
display: inline-block;
padding: 0 0 10px;
}
}
.app-form-item-label-left{
.app-form-item-label{
float: left;
text-align: right;
padding-right: 12px;
}
}
.app-form-item-label-right{
.app-form-item-label{
float: right;
text-align: left;
padding-left: 12px;
}
}
.app-form-item-label-top{
.app-form-item-label{
display: block;
padding-bottom: 10px;
}
}
.app-form-item-label-bottom{
.app-form-item-label{
display: block;
padding-top: 10px;
}
}
\ No newline at end of file
......@@ -21,12 +21,16 @@
:error="error"
:required="required"
:rules="rules"
:class="classes"
:label-width="this.isShowCaption ? !Object.is(this.labelPos, 'TOP') ? this.labelWidth : null : 0">
<span slot='label' v-if="this.isShowCaption && this.labelWidth > 0" :class="labelclasses">
{{this.isEmptyCaption ? '' : this.caption}}
</span>
:class="classes">
<div v-if="Object.is(this.labelPos,'BOTTOM') || Object.is(this.labelPos,'NONE') || !this.labelPos" class="slot-editor" :style="slotstyle">
<slot></slot>
</div>
<span v-if="!Object.is(this.labelPos,'NONE') && this.isShowCaption && this.labelWidth > 0" :style="labelstyle" :class="labelclasses">
{{this.isEmptyCaption ? '' : this.caption}}
</span>
<div v-if="Object.is(this.labelPos,'TOP') || Object.is(this.labelPos,'LEFT') || Object.is(this.labelPos,'RIGHT')" class="slot-editor" :style="slotstyle">
<slot></slot>
</div>
</form-item>
</div>
</div>
......@@ -167,9 +171,27 @@ export default class AppFormItem extends Vue {
* @memberof AppFormItem
*/
get classes(): string[] {
let posClass = '';
switch (this.labelPos) {
case 'TOP':
posClass = 'app-form-item-label-top';
break;
case 'LEFT':
posClass = 'app-form-item-label-left';
break;
case 'BOTTOM':
posClass = 'app-form-item-label-bottom';
break;
case 'RIGHT':
posClass = 'app-form-item-label-right';
break;
case 'NONE':
posClass = 'app-form-item-label-none';
break;
}
return [
'app-form-item',
Object.is(this.labelPos, 'TOP') ? 'app-form-item-label-top' : ''
posClass
];
}
......@@ -181,7 +203,33 @@ export default class AppFormItem extends Vue {
* @memberof AppFormItem
*/
get labelclasses():string{
return this.labelStyle?this.labelStyle:'';
return this.labelStyle?this.labelStyle+' app-form-item-label':'app-form-item-label';
}
/**
* label行内样式
*
* @readonly
* @type {string}
* @memberof AppFormItem
*/
get labelstyle():any{
return {width:this.labelWidth+'px'};
}
/**
* slot行内样式
*
* @readonly
* @type {string}
* @memberof AppFormItem
*/
get slotstyle():any{
if(Object.is(this.labelPos,'LEFT')){
return {marginLeft:this.labelWidth+'px'};
}else if(Object.is(this.labelPos,'RIGHT')){
return {marginRight:this.labelWidth+'px'};
}
}
/**
......
......@@ -3,7 +3,7 @@
@on-open-change="transferRefresh"
@on-change="dataChange"
v-model="dataRight"
:style="{width:width}"
:style="{width:width?width:'586px'}"
multiple
>
<Option class="hidden" :value="item" v-for="(item,i) in dataRight" :key="i">{{findLabel(item)}}</Option>
......@@ -17,44 +17,23 @@ import { ElSelect } from "element-ui/types/select";
@Component({})
export default class AppTransfer extends Vue {
/**
* 左侧框数据
*/
public dataLeft: any[] = [];
/**
* 右侧框数据
*/
public dataRight: any[] = [];
/**
* 穿梭框宽度
*/
@Prop() public width:any;
/**
* 代码表服务对象
*
* @type {CodeListService}
* @memberof AppTransfer
*/
public codeListService: CodeListService = new CodeListService({
$store: this.$store
});
/**
* 查询参数
* @type {*}
* @memberof AppTransfer
*/
public queryParam: any;
@Prop() public width: any;
/**
* 表单传入字符串值分隔符
*
* @type {string}
* @memberof AppTransfer
*/
@Prop() public valueSeparator?: string;
@Prop() public valueSeparator!: string;
/**
* 当前选中值
* @type {any}
......@@ -79,26 +58,20 @@ export default class AppTransfer extends Vue {
@Prop() public codelistType?: string;
/**
* 组件change事件,右侧框数据变化时
* 局部上下文导航参数
*
* @type {*}
* @memberof AppTransfer
*/
dataChange(e: any) {
let newVal: any;
newVal = e.join(`${this.valueSeparator}`);
if (newVal) {
this.$emit("change", newVal);
} else {
this.$emit("change", null);
}
}
@Prop() public localContext!: any;
/**
* 传入额外参数
* 局部导航参数
*
* @type {*}
* @memberof AppTransfer
*/
@Prop() public itemParam?: any;
@Prop() public localParam!: any;
/**
* 视图上下文
......@@ -118,6 +91,7 @@ export default class AppTransfer extends Vue {
/**
* 是否禁用
*
* @type {any}
* @memberof AppTransfer
*
......@@ -125,18 +99,38 @@ export default class AppTransfer extends Vue {
@Prop() public disabled?: any;
/**
* 是否支持过滤
* @type {boolean}
* placeholder
*
* @type {string}
* @memberof AppTransfer
*
*/
@Prop() public filterable?: boolean;
@Prop() public placeholder?: string;
/**
* 下拉选提示内容
* @type {string}
* 左侧框数据
*
* @type {any[]}
* @memberof AppTransfer
*/
@Prop() public placeholder?: string;
public dataLeft: any[] = [];
/**
* 右侧框数据
*
* @type {any[]}
* @memberof AppTransfer
*/
public dataRight: any[] = [];
/**
* 代码表服务对象
*
* @type {CodeListService}
* @memberof AppTransfer
*/
public codeListService: CodeListService = new CodeListService({$store: this.$store});
/**
* vue 生命周期
......@@ -147,8 +141,34 @@ export default class AppTransfer extends Vue {
this.dataHandle();
}
/**
* 组件change事件,右侧框数据变化时
*
* @memberof AppTransfer
*/
dataChange(e: any) {
let _valueSeparator: string = this.initValueSeparator();
let newVal: string = e.join(`${_valueSeparator}`);
if (newVal) {
this.$emit("change", newVal);
} else {
this.$emit("change", null);
}
}
/**
* 初始化valueSeparator
*
* @memberof AppTransfer
*/
public initValueSeparator() {
return this.valueSeparator?this.valueSeparator:",";
}
/**
* 数据处理
*
* @memberof AppTransfer
*/
public dataHandle() {
if (this.tag && Object.is(this.codelistType, "STATIC")) {
......@@ -167,14 +187,11 @@ export default class AppTransfer extends Vue {
// 参数处理
let _context = data.context;
let _param = data.param;
this.codeListService
.getItems(this.tag, _context, _param)
.then((res: any) => {
this.codeListService.getItems(this.tag, _context, _param).then((res: any) => {
this.dataLeft = res;
this.initLeft();
this.initRight();
})
.catch((error: any) => {
}).catch((error: any) => {
console.log(`----${this.tag}----代码表不存在`);
});
}
......@@ -189,30 +206,23 @@ export default class AppTransfer extends Vue {
*/
public handlePublicParams(arg: any) {
// 合并表单参数
arg.param = this.viewparams
? JSON.parse(JSON.stringify(this.viewparams))
: {};
arg.param = this.viewparams? JSON.parse(JSON.stringify(this.viewparams)): {};
arg.context = this.context ? JSON.parse(JSON.stringify(this.context)) : {};
// 附加参数处理
if (this.itemParam && this.itemParam.context) {
let _context = this.$util.formatData(
this.itemValue,
arg.context,
this.itemParam.context
);
if (this.localContext && Object.keys(this.localContext).length > 0) {
let _context = this.$util.computedNavData(this.itemValue,arg.context,arg.param,this.localContext);
Object.assign(arg.context, _context);
}
if (this.itemParam && this.itemParam.param) {
let _param = this.$util.formatData(
this.itemValue,
arg.param,
this.itemParam.param
);
if (this.localParam && Object.keys(this.localParam).length > 0) {
let _param = this.$util.computedNavData(this.itemValue,arg.context,arg.param,this.localParam);
Object.assign(arg.param, _param);
}
}
/**
* 初始化左侧框数据
*
* @memberof AppTransfer
*/
public initLeft() {
let left: any[] = [];
......@@ -222,46 +232,58 @@ export default class AppTransfer extends Vue {
this.dataLeft.push({
key: elem.id,
value: elem.value,
label: elem.label,
label: elem.text,
disabled: elem.disabled
});
});
}
/**
* 初始化右侧框数据
*
* @memberof AppTransfer
*/
public initRight() {
let _valueSeparator: any;
_valueSeparator = this.initValueSeparator();
let _data: any = this.itemValue;
if (_data) {
let newData: any[] = _data.split(`${this.valueSeparator}`);
let _dataRight: any = [];
let newData: any[] = _data.split(`${_valueSeparator}`);
this.dataLeft.forEach((elem: any) => {
newData.forEach((item: any) => {
if (item === elem.value) {
this.dataRight.push(elem.key);
_dataRight.push(elem.key);
}
});
});
this.dataRight = _dataRight;
}
}
/**
* 穿梭框打开时刷新数据
*
* @memberof AppTransfer
*/
public transferRefresh(e: any) {
if (e && this.codelistType === "DYNAMIC") {
this.dataLeft = [];
this.dataRight = [];
this.dataHandle();
}
}
/**
* 找到dataLeft中key与dataRight中item相等的元素,返回label
*
* @memberof AppTransfer
*/
public findLabel(item: any) {
for (const elem of this.dataLeft) {
if (elem.key === item) return elem.label;
}
}
}
</script>
......
......@@ -116,7 +116,7 @@ export default class DropDownList extends Vue {
* @memberof AppFormDRUIPart
*/
@Prop() public viewparams!: any;
/**
* 是否禁用
* @type {any}
......
......@@ -89,6 +89,7 @@ export default class EditView2Engine extends EditViewEngine {
*/
public onFormLoad(arg: any = {}): void {
super.onFormLoad(arg);
this.view.formData = arg;
if (this.getDRBar()) {
const tag = this.getDRBar().name;
this.setViewState2({ tag: tag, action: 'state', viewdata: this.view.vieparams });
......@@ -103,6 +104,7 @@ export default class EditView2Engine extends EditViewEngine {
*/
public onFormSave(arg: any = {}): void {
super.onFormSave(arg);
this.view.formData = arg;
if (this.getDRBar()) {
const tag = this.getDRBar().name;
this.setViewState2({ tag: tag, action: 'state', viewdata: this.view.viewparams });
......
......@@ -89,6 +89,7 @@ export default class EditView3Engine extends EditViewEngine {
*/
public onFormLoad(arg: any = {}): void {
super.onFormLoad(arg);
this.view.formData = arg;
if (this.getDrTab()) {
const tag = this.getDrTab().name;
this.setViewState2({ tag: tag, action: 'state', viewdata: this.view.viewparams });
......@@ -103,6 +104,7 @@ export default class EditView3Engine extends EditViewEngine {
*/
public onFormSave(arg: any = {}): void {
super.onFormSave(arg);
this.view.formData = arg;
if (this.getDrTab()) {
const tag = this.getDrTab().name;
this.setViewState2({ tag: tag, action: 'state', viewdata: this.view.viewparams });
......
......@@ -44,7 +44,7 @@ export class UIActionTool {
*/
private static formatData(actionTarget: any, args: any,parentContext:any,parentParams:any, _params: any): any {
let _data: any = {};
if (Object.is(actionTarget, 'SINGLEKEY')) {
if (Object.is(actionTarget, 'SINGLEKEY') || Object.is(actionTarget, 'NONE')) {
let [arg] = args;
Object.keys(_params).forEach((name: string) => {
let hasProperty = true;
......
......@@ -128,7 +128,7 @@ export class ViewTool {
const [{ pathName, parameterName }] = parameters;
routePath = `/${pathName}`;
if (Object.keys(data).length > 0) {
routePath = `${routePath}/${qs.stringify(data, { delimiter: ';' })}`;
routePath = `${routePath}?${qs.stringify(data, { delimiter: ';' })}`;
}
} else if (parameters.length === 2) {
let [arg] = args;
......@@ -138,7 +138,7 @@ export class ViewTool {
arg[_parameterName] : null;
routePath = `/${_pathName}/${_value}/${_pathName2}`;
if (Object.keys(data).length > 0) {
routePath = `${routePath}/${qs.stringify(data, { delimiter: ';' })}`;
routePath = `${routePath}?${qs.stringify(data, { delimiter: ';' })}`;
}
}
return routePath;
......
......@@ -1284,6 +1284,7 @@ export default class MainBase extends Vue implements ControlInterface {
*/
public uiAction(row: any, tag: any, $event: any) {
// this.rowClick(row, true);
$event.stopPropagation();
}
/**
......
......@@ -1265,6 +1265,7 @@ export default class MainBase extends Vue implements ControlInterface {
*/
public uiAction(row: any, tag: any, $event: any) {
// this.rowClick(row, true);
$event.stopPropagation();
}
/**
......
......@@ -1332,6 +1332,7 @@ export default class MainBase extends Vue implements ControlInterface {
*/
public uiAction(row: any, tag: any, $event: any) {
// this.rowClick(row, true);
$event.stopPropagation();
}
/**
......
......@@ -1284,6 +1284,7 @@ export default class MainBase extends Vue implements ControlInterface {
*/
public uiAction(row: any, tag: any, $event: any) {
// this.rowClick(row, true);
$event.stopPropagation();
}
/**
......
......@@ -35,6 +35,10 @@ zuul:
path: /uaa/**
serviceId: ibzuaa-api
stripPrefix: false
config:
path: /config/**
serviceId: ibzuaa-api
stripPrefix: false
oucore:
path: /ibzorganizations/**
serviceId: ibzou-api
......
......@@ -12,6 +12,10 @@ zuul:
path: /uaa/**
serviceId: ibzuaa-api
stripPrefix: false
config:
path: /config/**
serviceId: ibzuaa-api
stripPrefix: false
oucore:
path: /ibzorganizations/**
serviceId: ibzou-api
......
......@@ -22,17 +22,17 @@ import lombok.*;
import org.springframework.data.annotation.Transient;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.baomidou.mybatisplus.annotation.*;
import cn.ibizlab.util.domain.EntityMP;
/**
* 实体[角色/用户组]
*/
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(value = "handler")
@TableName(value = "IBZWFGROUP",resultMap = "WFGroupResultMap")
public class WFGroup extends EntityMP implements Serializable {
......
......@@ -29,7 +29,6 @@ import org.springframework.data.annotation.Transient;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class WFHistory extends EntityBase implements Serializable {
/**
......
......@@ -22,17 +22,17 @@ import lombok.*;
import org.springframework.data.annotation.Transient;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.baomidou.mybatisplus.annotation.*;
import cn.ibizlab.util.domain.EntityMP;
/**
* 实体[成员]
*/
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(value = "handler")
@TableName(value = "IBZWFMEMBER",resultMap = "WFMemberResultMap")
public class WFMember extends EntityMP implements Serializable {
......
......@@ -22,17 +22,17 @@ import lombok.*;
import org.springframework.data.annotation.Transient;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.baomidou.mybatisplus.annotation.*;
import cn.ibizlab.util.domain.EntityMP;
/**
* 实体[流程定义]
*/
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(value = "handler")
@TableName(value = "IBZWFDEFINITION",resultMap = "WFProcessDefinitionResultMap")
public class WFProcessDefinition extends EntityMP implements Serializable {
......
......@@ -29,7 +29,6 @@ import org.springframework.data.annotation.Transient;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class WFProcessInstance extends EntityBase implements Serializable {
/**
......
......@@ -29,7 +29,6 @@ import org.springframework.data.annotation.Transient;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class WFProcessNode extends EntityBase implements Serializable {
/**
......
......@@ -29,7 +29,6 @@ import org.springframework.data.annotation.Transient;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class WFREModel extends EntityBase implements Serializable {
/**
......
......@@ -22,17 +22,17 @@ import lombok.*;
import org.springframework.data.annotation.Transient;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.baomidou.mybatisplus.annotation.*;
import cn.ibizlab.util.domain.EntityMP;
/**
* 实体[系统]
*/
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(value = "handler")
@TableName(value = "IBZPSSYSTEM",resultMap = "WFSystemResultMap")
public class WFSystem extends EntityMP implements Serializable {
......
......@@ -29,7 +29,6 @@ import org.springframework.data.annotation.Transient;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class WFTask extends EntityBase implements Serializable {
/**
......
......@@ -29,7 +29,6 @@ import org.springframework.data.annotation.Transient;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class WFTaskWay extends EntityBase implements Serializable {
/**
......
......@@ -22,17 +22,17 @@ import lombok.*;
import org.springframework.data.annotation.Transient;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.baomidou.mybatisplus.annotation.*;
import cn.ibizlab.util.domain.EntityMP;
/**
* 实体[用户]
*/
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(value = "handler")
@TableName(value = "IBZUSER",resultMap = "WFUserResultMap")
public class WFUser extends EntityMP implements Serializable {
......
......@@ -22,4 +22,9 @@ public class IBZUAAFallback implements IBZUAAFeignClient {
public AuthenticationUser loginByUsername(String username) {
return null;
}
@Override
public String getPublicKey() {
return null;
}
}
......@@ -2,6 +2,7 @@ package cn.ibizlab.util.client;
import cn.ibizlab.util.security.AuthenticationUser;
import cn.ibizlab.util.security.AuthorizationLogin;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
import com.alibaba.fastjson.JSONObject;
......@@ -28,4 +29,8 @@ public interface IBZUAAFeignClient
@PostMapping(value = "/uaa/loginbyusername")
AuthenticationUser loginByUsername(@RequestBody String username);
@Cacheable(value="ibzuaa_publickey")
@GetMapping(value = "/uaa/publickey")
String getPublicKey();
}
package cn.ibizlab.util.security;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Clock;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.DefaultClock;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
public interface AuthTokenUtil {
@Component
public class AuthTokenUtil implements Serializable {
String generateToken(UserDetails userDetails);
private static final long serialVersionUID = -3301605591108950415L;
private Clock clock = DefaultClock.INSTANCE;
Boolean validateToken(String token, UserDetails userDetails);
@Value("${ibiz.jwt.secret:ibzsecret}")
private String secret;
String getUsernameFromToken(String token);
@Value("${ibiz.jwt.expiration:7200000}")
private Long expiration;
@Value("${ibiz.jwt.header:Authorization}")
private String tokenHeader;
public String getUsernameFromToken(String token) {
return getClaimFromToken(token, Claims::getSubject);
}
public Date getIssuedAtDateFromToken(String token) {
return getClaimFromToken(token, Claims::getIssuedAt);
}
public Date getExpirationDateFromToken(String token) {
return getClaimFromToken(token, Claims::getExpiration);
}
public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
final Claims claims = getAllClaimsFromToken(token);
return claimsResolver.apply(claims);
}
private Claims getAllClaimsFromToken(String token) {
return Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
}
private Boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(clock.now());
}
private Boolean isCreatedBeforeLastPasswordReset(Date created, Date lastPasswordReset) {
return (lastPasswordReset != null && created.before(lastPasswordReset));
}
private Boolean ignoreTokenExpiration(String token) {
// here you specify tokens, for that the expiration is ignored
return false;
}
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
return doGenerateToken(claims, userDetails.getUsername());
}
private String doGenerateToken(Map<String, Object> claims, String subject) {
final Date createdDate = clock.now();
final Date expirationDate = calculateExpirationDate(createdDate);
return Jwts.builder()
.setClaims(claims)
.setSubject(subject)
.setIssuedAt(createdDate)
.setExpiration(expirationDate)
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
public Boolean canTokenBeRefreshed(String token, Date lastPasswordReset) {
final Date created = getIssuedAtDateFromToken(token);
return !isCreatedBeforeLastPasswordReset(created, lastPasswordReset)
&& (!isTokenExpired(token) || ignoreTokenExpiration(token));
}
public String refreshToken(String token) {
final Date createdDate = clock.now();
final Date expirationDate = calculateExpirationDate(createdDate);
final Claims claims = getAllClaimsFromToken(token);
claims.setIssuedAt(createdDate);
claims.setExpiration(expirationDate);
return Jwts.builder()
.setClaims(claims)
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
public Boolean validateToken(String token, UserDetails userDetails) {
AuthenticationUser user = (AuthenticationUser) userDetails;
final Date created = getIssuedAtDateFromToken(token);
return (!isTokenExpired(token) );
}
private Date calculateExpirationDate(Date createdDate) {
return new Date(createdDate.getTime() + expiration);
}
/**
* Get the login of the current user.
*
* @return the login of the current user
*/
public static Optional<String> getCurrentUserLogin() {
SecurityContext securityContext = SecurityContextHolder.getContext();
return Optional.ofNullable(securityContext.getAuthentication())
.map(authentication -> {
if (authentication.getPrincipal() instanceof UserDetails) {
UserDetails springSecurityUser = (UserDetails) authentication.getPrincipal();
return springSecurityUser.getUsername();
} else if (authentication.getPrincipal() instanceof String) {
return (String) authentication.getPrincipal();
}
return null;
});
}
/**
* Check if a user is authenticated.
*
* @return true if the user is authenticated, false otherwise
*/
public static boolean isAuthenticated() {
SecurityContext securityContext = SecurityContextHolder.getContext();
return Optional.ofNullable(securityContext.getAuthentication())
.map(authentication -> authentication.getAuthorities().stream()
.noneMatch(grantedAuthority -> grantedAuthority.getAuthority().equals("ANONYMOUS")))
.orElse(false);
}
/**
* If the current user has a specific authority (security role).
* <p>
* The name of this method comes from the isUserInRole() method in the Servlet API
*
* @param authority the authority to check
* @return true if the current user has the authority, false otherwise
*/
public static boolean isCurrentUserInRole(String authority) {
SecurityContext securityContext = SecurityContextHolder.getContext();
return Optional.ofNullable(securityContext.getAuthentication())
.map(authentication -> authentication.getAuthorities().stream()
.anyMatch(grantedAuthority -> grantedAuthority.getAuthority().equals(authority)))
.orElse(false);
}
}
package cn.ibizlab.util.security;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Clock;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.DefaultClock;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
@Component
@ConditionalOnExpression("(!${ibiz.enablePermissionValid:false})&&'${ibiz.auth.service:UAATokenUtil}'.equals('SimpleTokenUtil')")
public class SimpleTokenUtil implements AuthTokenUtil,Serializable {
private static final long serialVersionUID = -3301605591108950415L;
private Clock clock = DefaultClock.INSTANCE;
@Value("${ibiz.jwt.secret:ibzsecret}")
private String secret;
@Value("${ibiz.jwt.expiration:7200000}")
private Long expiration;
@Value("${ibiz.jwt.header:Authorization}")
private String tokenHeader;
public String getUsernameFromToken(String token) {
return getClaimFromToken(token, Claims::getSubject);
}
public Date getIssuedAtDateFromToken(String token) {
return getClaimFromToken(token, Claims::getIssuedAt);
}
public Date getExpirationDateFromToken(String token) {
return getClaimFromToken(token, Claims::getExpiration);
}
public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
final Claims claims = getAllClaimsFromToken(token);
return claimsResolver.apply(claims);
}
private Claims getAllClaimsFromToken(String token) {
return Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
}
private Boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(clock.now());
}
private Boolean isCreatedBeforeLastPasswordReset(Date created, Date lastPasswordReset) {
return (lastPasswordReset != null && created.before(lastPasswordReset));
}
private Boolean ignoreTokenExpiration(String token) {
// here you specify tokens, for that the expiration is ignored
return false;
}
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
return doGenerateToken(claims, userDetails.getUsername());
}
private String doGenerateToken(Map<String, Object> claims, String subject) {
final Date createdDate = clock.now();
final Date expirationDate = calculateExpirationDate(createdDate);
return Jwts.builder()
.setClaims(claims)
.setSubject(subject)
.setIssuedAt(createdDate)
.setExpiration(expirationDate)
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
public Boolean canTokenBeRefreshed(String token, Date lastPasswordReset) {
final Date created = getIssuedAtDateFromToken(token);
return !isCreatedBeforeLastPasswordReset(created, lastPasswordReset)
&& (!isTokenExpired(token) || ignoreTokenExpiration(token));
}
public String refreshToken(String token) {
final Date createdDate = clock.now();
final Date expirationDate = calculateExpirationDate(createdDate);
final Claims claims = getAllClaimsFromToken(token);
claims.setIssuedAt(createdDate);
claims.setExpiration(expirationDate);
return Jwts.builder()
.setClaims(claims)
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
public Boolean validateToken(String token, UserDetails userDetails) {
AuthenticationUser user = (AuthenticationUser) userDetails;
final Date created = getIssuedAtDateFromToken(token);
return (!isTokenExpired(token) );
}
private Date calculateExpirationDate(Date createdDate) {
return new Date(createdDate.getTime() + expiration);
}
/**
* Get the login of the current user.
*
* @return the login of the current user
*/
public static Optional<String> getCurrentUserLogin() {
SecurityContext securityContext = SecurityContextHolder.getContext();
return Optional.ofNullable(securityContext.getAuthentication())
.map(authentication -> {
if (authentication.getPrincipal() instanceof UserDetails) {
UserDetails springSecurityUser = (UserDetails) authentication.getPrincipal();
return springSecurityUser.getUsername();
} else if (authentication.getPrincipal() instanceof String) {
return (String) authentication.getPrincipal();
}
return null;
});
}
/**
* Check if a user is authenticated.
*
* @return true if the user is authenticated, false otherwise
*/
public static boolean isAuthenticated() {
SecurityContext securityContext = SecurityContextHolder.getContext();
return Optional.ofNullable(securityContext.getAuthentication())
.map(authentication -> authentication.getAuthorities().stream()
.noneMatch(grantedAuthority -> grantedAuthority.getAuthority().equals("ANONYMOUS")))
.orElse(false);
}
/**
* If the current user has a specific authority (security role).
* <p>
* The name of this method comes from the isUserInRole() method in the Servlet API
*
* @param authority the authority to check
* @return true if the current user has the authority, false otherwise
*/
public static boolean isCurrentUserInRole(String authority) {
SecurityContext securityContext = SecurityContextHolder.getContext();
return Optional.ofNullable(securityContext.getAuthentication())
.map(authentication -> authentication.getAuthorities().stream()
.anyMatch(grantedAuthority -> grantedAuthority.getAuthority().equals(authority)))
.orElse(false);
}
}
package cn.ibizlab.util.security;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Clock;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.DefaultClock;
import lombok.SneakyThrows;
import cn.ibizlab.util.client.IBZUAAFeignClient;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.FileInputStream;
import java.io.Serializable;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
@Component
@ConditionalOnExpression("${ibiz.enablePermissionValid:false}||'${ibiz.auth.service:UAATokenUtil}'.equals('UAATokenUtil')")
public class UAATokenUtil implements AuthTokenUtil, Serializable {
private static final long serialVersionUID = -3301605591108950415L;
private Clock clock = DefaultClock.INSTANCE;
@Value("${ibiz.jwt.secret:ibzsecret}")
private String secret;
@Value("${ibiz.jwt.expiration:7200000}")
private Long expiration;
@Value("${ibiz.jwt.header:Authorization}")
private String tokenHeader;
@Autowired
private IBZUAAFeignClient uaaFeignClient;
public String getUsernameFromToken(String token) {
return getClaimFromToken(token, Claims::getSubject);
}
public Date getIssuedAtDateFromToken(String token) {
return getClaimFromToken(token, Claims::getIssuedAt);
}
public Date getExpirationDateFromToken(String token) {
return getClaimFromToken(token, Claims::getExpiration);
}
public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
final Claims claims = getAllClaimsFromToken(token);
return claimsResolver.apply(claims);
}
public Claims getAllClaimsFromToken(String token) {
PublicKey publicKey = getPublicKey(getPublicKeyString());
return Jwts.parser()
.setSigningKey(publicKey)
.parseClaimsJws(token)
.getBody();
}
private Boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(clock.now());
}
public String generateToken(UserDetails userDetails) {
return null;
}
public Boolean validateToken(String token, UserDetails userDetails) {
AuthenticationUser user = (AuthenticationUser) userDetails;
final Date created = getIssuedAtDateFromToken(token);
return (!isTokenExpired(token) );
}
private String getPublicKeyString(){
return uaaFeignClient.getPublicKey();
}
/**
* 获取PublicKey对象
* @param publicKeyBase64
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
*/
@SneakyThrows
public PublicKey getPublicKey(String publicKeyBase64) {
byte[] byteKey = Base64.decodeBase64(publicKeyBase64);
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(byteKey);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePublic(x509EncodedKeySpec);
}
}
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册