forked from github/dataease
refactor: 查看分享链接使用独立拦截器
This commit is contained in:
parent
7beb636ff4
commit
bcd786c48c
@ -50,6 +50,7 @@ public class ShiroConfig {
|
|||||||
filterMap.put("f2cPerms", new F2CPermissionsFilter());
|
filterMap.put("f2cPerms", new F2CPermissionsFilter());
|
||||||
filterMap.put("jwt", new JWTFilter());
|
filterMap.put("jwt", new JWTFilter());
|
||||||
filterMap.put("logout", new F2CLogoutFilter());
|
filterMap.put("logout", new F2CLogoutFilter());
|
||||||
|
filterMap.put("link", new F2CLinkFilter());
|
||||||
factoryBean.setSecurityManager(securityManager);
|
factoryBean.setSecurityManager(securityManager);
|
||||||
factoryBean.setLoginUrl("/login");
|
factoryBean.setLoginUrl("/login");
|
||||||
factoryBean.setUnauthorizedUrl("/login");
|
factoryBean.setUnauthorizedUrl("/login");
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
package io.dataease.auth.filter;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import com.auth0.jwt.JWT;
|
||||||
|
import com.auth0.jwt.interfaces.Claim;
|
||||||
|
import com.auth0.jwt.interfaces.DecodedJWT;
|
||||||
|
import io.dataease.auth.config.RsaProperties;
|
||||||
|
import io.dataease.auth.util.JWTUtils;
|
||||||
|
import io.dataease.auth.util.LinkUtil;
|
||||||
|
import io.dataease.auth.util.RsaUtil;
|
||||||
|
import io.dataease.base.domain.PanelLink;
|
||||||
|
import io.dataease.commons.utils.LogUtil;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.shiro.web.filter.authc.AnonymousFilter;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
|
import javax.servlet.ServletResponse;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
public class F2CLinkFilter extends AnonymousFilter {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(F2CLogoutFilter.class);
|
||||||
|
|
||||||
|
private static final String LINK_TOKEN_KEY = "LINK-PWD-TOKEN";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) {
|
||||||
|
try{
|
||||||
|
HttpServletRequest req = (HttpServletRequest) request;
|
||||||
|
String link_token = req.getHeader(LINK_TOKEN_KEY);
|
||||||
|
DecodedJWT jwt = JWT.decode(link_token);
|
||||||
|
Claim resourceId = jwt.getClaim("resourceId");
|
||||||
|
String id = resourceId.asString();
|
||||||
|
PanelLink panelLink = LinkUtil.queryLink(id);
|
||||||
|
if (ObjectUtil.isEmpty(panelLink)) return false;
|
||||||
|
if (!panelLink.getEnablePwd()) {
|
||||||
|
panelLink.setPwd("dataease");
|
||||||
|
}
|
||||||
|
return JWTUtils.verifyLink(link_token, id, RsaUtil.decryptByPrivateKey(RsaProperties.privateKey, panelLink.getPwd()));
|
||||||
|
}catch (Exception e) {
|
||||||
|
LogUtil.error(e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -41,8 +41,7 @@ public class ShiroServiceImpl implements ShiroService {
|
|||||||
|
|
||||||
//验证链接
|
//验证链接
|
||||||
filterChainDefinitionMap.put("/api/link/validate**", ANON);
|
filterChainDefinitionMap.put("/api/link/validate**", ANON);
|
||||||
filterChainDefinitionMap.put("/panel/group/findOne/**", ANON);
|
|
||||||
filterChainDefinitionMap.put("/chart/view/getData/**", ANON);
|
|
||||||
|
|
||||||
|
|
||||||
filterChainDefinitionMap.put("/system/ui/**", ANON);
|
filterChainDefinitionMap.put("/system/ui/**", ANON);
|
||||||
@ -59,9 +58,16 @@ public class ShiroServiceImpl implements ShiroService {
|
|||||||
filterChainDefinitionMap.put("/tokenExpired", ANON);
|
filterChainDefinitionMap.put("/tokenExpired", ANON);
|
||||||
filterChainDefinitionMap.put("/downline", ANON);
|
filterChainDefinitionMap.put("/downline", ANON);
|
||||||
filterChainDefinitionMap.put("/common-files/**", ANON);
|
filterChainDefinitionMap.put("/common-files/**", ANON);
|
||||||
|
|
||||||
filterChainDefinitionMap.put("/api/auth/logout", "logout");
|
filterChainDefinitionMap.put("/api/auth/logout", "logout");
|
||||||
|
|
||||||
|
filterChainDefinitionMap.put("/api/link/resourceDetail/**", "link");
|
||||||
|
filterChainDefinitionMap.put("/api/link/viewDetail/**", "link");
|
||||||
|
|
||||||
filterChainDefinitionMap.put("/**", "authc");
|
filterChainDefinitionMap.put("/**", "authc");
|
||||||
|
|
||||||
filterChainDefinitionMap.put("/**", "jwt");
|
filterChainDefinitionMap.put("/**", "jwt");
|
||||||
|
|
||||||
return filterChainDefinitionMap;
|
return filterChainDefinitionMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
22
backend/src/main/java/io/dataease/auth/util/LinkUtil.java
Normal file
22
backend/src/main/java/io/dataease/auth/util/LinkUtil.java
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package io.dataease.auth.util;
|
||||||
|
|
||||||
|
import io.dataease.base.domain.PanelLink;
|
||||||
|
import io.dataease.service.panel.PanelLinkService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class LinkUtil {
|
||||||
|
|
||||||
|
|
||||||
|
private static PanelLinkService panelLinkService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public void setPanelLinkService(PanelLinkService panelLinkService) {
|
||||||
|
LinkUtil.panelLinkService = panelLinkService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PanelLink queryLink(String resourceId) {
|
||||||
|
return panelLinkService.findOne(resourceId);
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package io.dataease.controller.panel.api;
|
package io.dataease.controller.panel.api;
|
||||||
|
|
||||||
|
|
||||||
|
import io.dataease.controller.request.chart.ChartExtRequest;
|
||||||
import io.dataease.controller.request.panel.link.EnablePwdRequest;
|
import io.dataease.controller.request.panel.link.EnablePwdRequest;
|
||||||
import io.dataease.controller.request.panel.link.LinkRequest;
|
import io.dataease.controller.request.panel.link.LinkRequest;
|
||||||
import io.dataease.controller.request.panel.link.PasswordRequest;
|
import io.dataease.controller.request.panel.link.PasswordRequest;
|
||||||
@ -40,4 +41,12 @@ public interface LinkApi {
|
|||||||
@ApiOperation("验证密码")
|
@ApiOperation("验证密码")
|
||||||
@PostMapping("/validatePwd")
|
@PostMapping("/validatePwd")
|
||||||
boolean validatePwd(PasswordRequest request) throws Exception;
|
boolean validatePwd(PasswordRequest request) throws Exception;
|
||||||
|
|
||||||
|
@ApiOperation("资源详息")
|
||||||
|
@PostMapping("/resourceDetail/{resourceId}")
|
||||||
|
Object resourceDetail(@PathVariable String resourceId);
|
||||||
|
|
||||||
|
@ApiOperation("视图详息")
|
||||||
|
@PostMapping("/viewDetail/{viewId}")
|
||||||
|
Object viewDetail(@PathVariable String viewId, @RequestBody ChartExtRequest requestList) throws Exception;
|
||||||
}
|
}
|
||||||
|
@ -4,18 +4,22 @@ package io.dataease.controller.panel.server;
|
|||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import io.dataease.base.domain.PanelLink;
|
import io.dataease.base.domain.PanelLink;
|
||||||
import io.dataease.controller.panel.api.LinkApi;
|
import io.dataease.controller.panel.api.LinkApi;
|
||||||
|
import io.dataease.controller.request.chart.ChartExtRequest;
|
||||||
import io.dataease.controller.request.panel.link.EnablePwdRequest;
|
import io.dataease.controller.request.panel.link.EnablePwdRequest;
|
||||||
import io.dataease.controller.request.panel.link.LinkRequest;
|
import io.dataease.controller.request.panel.link.LinkRequest;
|
||||||
import io.dataease.controller.request.panel.link.PasswordRequest;
|
import io.dataease.controller.request.panel.link.PasswordRequest;
|
||||||
import io.dataease.controller.request.panel.link.ValidateRequest;
|
import io.dataease.controller.request.panel.link.ValidateRequest;
|
||||||
import io.dataease.dto.panel.link.GenerateDto;
|
import io.dataease.dto.panel.link.GenerateDto;
|
||||||
import io.dataease.dto.panel.link.ValidateDto;
|
import io.dataease.dto.panel.link.ValidateDto;
|
||||||
|
import io.dataease.service.chart.ChartViewService;
|
||||||
import io.dataease.service.panel.PanelLinkService;
|
import io.dataease.service.panel.PanelLinkService;
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
@ -27,6 +31,9 @@ public class LinkServer implements LinkApi {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private PanelLinkService panelLinkService;
|
private PanelLinkService panelLinkService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ChartViewService chartViewService;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void replacePwd(@RequestBody PasswordRequest request) {
|
public void replacePwd(@RequestBody PasswordRequest request) {
|
||||||
@ -73,4 +80,14 @@ public class LinkServer implements LinkApi {
|
|||||||
public boolean validatePwd(@RequestBody PasswordRequest request) throws Exception {
|
public boolean validatePwd(@RequestBody PasswordRequest request) throws Exception {
|
||||||
return panelLinkService.validatePwd(request);
|
return panelLinkService.validatePwd(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object resourceDetail(@PathVariable String resourceId) {
|
||||||
|
return panelLinkService.resourceInfo(resourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object viewDetail(String viewId, ChartExtRequest requestList) throws Exception{
|
||||||
|
return chartViewService.getData(viewId, requestList);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,9 @@ import com.google.gson.Gson;
|
|||||||
import io.dataease.auth.config.RsaProperties;
|
import io.dataease.auth.config.RsaProperties;
|
||||||
import io.dataease.auth.util.JWTUtils;
|
import io.dataease.auth.util.JWTUtils;
|
||||||
import io.dataease.auth.util.RsaUtil;
|
import io.dataease.auth.util.RsaUtil;
|
||||||
|
import io.dataease.base.domain.PanelGroupWithBLOBs;
|
||||||
import io.dataease.base.domain.PanelLink;
|
import io.dataease.base.domain.PanelLink;
|
||||||
|
import io.dataease.base.mapper.PanelGroupMapper;
|
||||||
import io.dataease.base.mapper.PanelLinkMapper;
|
import io.dataease.base.mapper.PanelLinkMapper;
|
||||||
import io.dataease.commons.utils.ServletUtils;
|
import io.dataease.commons.utils.ServletUtils;
|
||||||
import io.dataease.controller.request.panel.link.EnablePwdRequest;
|
import io.dataease.controller.request.panel.link.EnablePwdRequest;
|
||||||
@ -32,6 +34,9 @@ public class PanelLinkService {
|
|||||||
@Resource
|
@Resource
|
||||||
private PanelLinkMapper mapper;
|
private PanelLinkMapper mapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private PanelGroupMapper panelGroupMapper;
|
||||||
|
|
||||||
public void changeValid(LinkRequest request){
|
public void changeValid(LinkRequest request){
|
||||||
PanelLink po = new PanelLink();
|
PanelLink po = new PanelLink();
|
||||||
po.setResourceId(request.getResourceId());
|
po.setResourceId(request.getResourceId());
|
||||||
@ -117,7 +122,16 @@ public class PanelLinkService {
|
|||||||
public Boolean validateHeads(PanelLink panelLink) throws Exception{
|
public Boolean validateHeads(PanelLink panelLink) throws Exception{
|
||||||
HttpServletRequest request = ServletUtils.request();
|
HttpServletRequest request = ServletUtils.request();
|
||||||
String token = request.getHeader("LINK-PWD-TOKEN");
|
String token = request.getHeader("LINK-PWD-TOKEN");
|
||||||
if (StringUtils.isEmpty(token) || StringUtils.equals("undefined", token) || StringUtils.equals("null", token)) return false;
|
if (!panelLink.getEnablePwd() || StringUtils.isEmpty(token) || StringUtils.equals("undefined", token) || StringUtils.equals("null", token)) {
|
||||||
|
String resourceId = panelLink.getResourceId();
|
||||||
|
String pwd = "dataease";
|
||||||
|
String tk = JWTUtils.signLink(resourceId, pwd);
|
||||||
|
HttpServletResponse httpServletResponse = ServletUtils.response();
|
||||||
|
httpServletResponse.addHeader("Access-Control-Expose-Headers", "LINK-PWD-TOKEN");
|
||||||
|
httpServletResponse.setHeader("LINK-PWD-TOKEN", tk);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(panelLink.getPwd())) return false;
|
||||||
boolean verify = JWTUtils.verifyLink(token, panelLink.getResourceId(), decryptParam(panelLink.getPwd()));
|
boolean verify = JWTUtils.verifyLink(token, panelLink.getResourceId(), decryptParam(panelLink.getPwd()));
|
||||||
return verify;
|
return verify;
|
||||||
}
|
}
|
||||||
@ -137,4 +151,9 @@ public class PanelLinkService {
|
|||||||
return pass;
|
return pass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PanelGroupWithBLOBs resourceInfo(String resourceId) {
|
||||||
|
return panelGroupMapper.selectByPrimaryKey(resourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,17 @@ export function loadGenerate(resourceId) {
|
|||||||
|
|
||||||
export function loadResource(resourceId) {
|
export function loadResource(resourceId) {
|
||||||
return request({
|
return request({
|
||||||
url: 'panel/group/findOne/' + resourceId,
|
url: 'api/link/resourceDetail/' + resourceId,
|
||||||
method: 'get'
|
method: 'post'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function viewInfo(id, data) {
|
||||||
|
return request({
|
||||||
|
url: 'api/link/viewDetail/' + id,
|
||||||
|
method: 'post',
|
||||||
|
timeout: 30000,
|
||||||
|
hideMsg: true,
|
||||||
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
<script>
|
<script>
|
||||||
|
|
||||||
import { viewData } from '@/api/panel/panel'
|
import { viewData } from '@/api/panel/panel'
|
||||||
|
import { viewInfo } from '@/api/link'
|
||||||
import ChartComponent from '@/views/chart/components/ChartComponent.vue'
|
import ChartComponent from '@/views/chart/components/ChartComponent.vue'
|
||||||
import TableNormal from '@/views/chart/components/table/TableNormal'
|
import TableNormal from '@/views/chart/components/table/TableNormal'
|
||||||
import LabelNormal from '../../../views/chart/components/normal/LabelNormal'
|
import LabelNormal from '../../../views/chart/components/normal/LabelNormal'
|
||||||
@ -35,7 +36,7 @@ import { isChange } from '@/utils/conditionUtil'
|
|||||||
import { BASE_CHART_STRING } from '@/views/chart/chart/chart'
|
import { BASE_CHART_STRING } from '@/views/chart/chart/chart'
|
||||||
import eventBus from '@/components/canvas/utils/eventBus'
|
import eventBus from '@/components/canvas/utils/eventBus'
|
||||||
import { deepCopy } from '@/components/canvas/utils/utils'
|
import { deepCopy } from '@/components/canvas/utils/utils'
|
||||||
|
import { getToken, getLinkToken } from '@/utils/auth'
|
||||||
export default {
|
export default {
|
||||||
name: 'UserView',
|
name: 'UserView',
|
||||||
components: { ChartComponent, TableNormal, LabelNormal },
|
components: { ChartComponent, TableNormal, LabelNormal },
|
||||||
@ -161,7 +162,14 @@ export default {
|
|||||||
if (id) {
|
if (id) {
|
||||||
this.requestStatus = 'waiting'
|
this.requestStatus = 'waiting'
|
||||||
this.message = null
|
this.message = null
|
||||||
viewData(id, this.filter).then(response => {
|
|
||||||
|
// 增加判断 仪表板公共连接中使用viewInfo 正常使用viewData
|
||||||
|
let method = viewData
|
||||||
|
if (!getToken() && getLinkToken()) {
|
||||||
|
method = viewInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
method(id, this.filter).then(response => {
|
||||||
// 将视图传入echart组件
|
// 将视图传入echart组件
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
this.chart = response.data
|
this.chart = response.data
|
||||||
|
@ -79,8 +79,8 @@ const checkAuth = response => {
|
|||||||
store.dispatch('user/refreshToken', refreshToken)
|
store.dispatch('user/refreshToken', refreshToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.headers[LinkTokenKey.toLocaleLowerCase()]) {
|
if (response.headers[LinkTokenKey.toLocaleLowerCase()] || (response.config.headers && response.config.headers[LinkTokenKey.toLocaleLowerCase()])) {
|
||||||
const linkToken = response.headers[LinkTokenKey.toLocaleLowerCase()]
|
const linkToken = response.headers[LinkTokenKey.toLocaleLowerCase()] || response.config.headers[LinkTokenKey.toLocaleLowerCase()]
|
||||||
setLinkToken(linkToken)
|
setLinkToken(linkToken)
|
||||||
}
|
}
|
||||||
// 许可状态改变 刷新页面
|
// 许可状态改变 刷新页面
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
<div class="input-layout">
|
<div class="input-layout">
|
||||||
<div class="input-main">
|
<div class="input-main">
|
||||||
<div class="div-input">
|
<div class="div-input">
|
||||||
<el-form ref="pwdForm" :model="form" :rules="rule" size="small">
|
<el-form ref="pwdForm" :model="form" :rules="rule" size="small" @submit.native.prevent>
|
||||||
<el-form-item prop="password">
|
<el-form-item prop="password">
|
||||||
<el-input v-model="form.password" maxlength="4" show-password class="real-input" :placeholder="$t('pblink.input_placeholder')" />
|
<el-input v-model="form.password" maxlength="4" show-password class="real-input" :placeholder="$t('pblink.input_placeholder')" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -65,8 +65,25 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
this.bindKey()
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
this.unBindKey()
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
entryKey(event) {
|
||||||
|
const keyCode = event.keyCode
|
||||||
|
if (keyCode === 13) {
|
||||||
|
this.refresh()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
bindKey() {
|
||||||
|
document.addEventListener('keypress', this.entryKey)
|
||||||
|
},
|
||||||
|
unBindKey() {
|
||||||
|
document.removeEventListener('keypress', this.entryKey)
|
||||||
|
},
|
||||||
// 验证密码是否正确 如果正确 设置请求头部带LINK-PWD-TOKEN=entrypt(pwd)再刷新页面
|
// 验证密码是否正确 如果正确 设置请求头部带LINK-PWD-TOKEN=entrypt(pwd)再刷新页面
|
||||||
refresh() {
|
refresh() {
|
||||||
this.$refs.pwdForm.validate(valid => {
|
this.$refs.pwdForm.validate(valid => {
|
||||||
|
Loading…
Reference in New Issue
Block a user