vue前端img访问鉴权,后端进行拦截

wengelovelian 2024-06-25 09:33:05 阅读 55

此文章为了解决匿名可以访问图片问题,有的文章是重构了el-img组件,使用blob重新进行加载。该文章是换个思路,在图片访问地址后面追加token参数,后端进行拦截,判断token是否有效,无效则拦截。反之通过。同时会校验是否同一台电脑、同一浏览器、同一操作系统、同一登录地点

前端:

image-preview组件:

<template>

<el-image

:src="`${realSrc}`"

fit="cover"

:style="`width:${realWidth};height:${realHeight};`"

:preview-src-list="realSrcList"

append-to-body="true"

>

<template #error>

<div class="image-slot">

<el-icon><picture-filled /></el-icon>

</div>

</template>

</el-image>

</template>

<script setup>

import { isExternal } from "@/utils/validate";

import { getToken } from "@/utils/auth";

import {watch} from "vue";

const tokenInfo = ref(getToken())

const props = defineProps({

src: {

type: String,

required: true

},

srcViewerList: {

type: Array

},

width: {

type: [Number, String],

default: ""

},

height: {

type: [Number, String],

default: ""

}

});

const realSrc = computed(() => {

let real_src = props.src.split(",")[0];

if (isExternal(real_src)) {

return real_src;

}

return import.meta.env.VITE_APP_BASE_API + real_src + '?token=' + tokenInfo.value;

});

const realSrcList = ref([]);

watch(() => {

props.srcViewerList.forEach(item => {

realSrcList.value.push(item + '?token=' + tokenInfo.value)

});

})

// const realSrcList = computed(() => {

// let real_src_list = props.src.split(",");

// let srcList = [];

// real_src_list.forEach(item => {

// if (isExternal(item)) {

// return srcList.push(item);

// }

// return srcList.push(import.meta.env.VITE_APP_BASE_API + item + '?token=' + tokenInfo.value);

// });

// return srcList;

// });

const realWidth = computed(() =>

typeof props.width == "string" ? props.width : `${props.width}px`

);

const realHeight = computed(() =>

typeof props.height == "string" ? props.height : `${props.height}px`

);

</script>

<style lang="scss" scoped>

.el-image {

border-radius: 5px;

background-color: #ebeef5;

box-shadow: 0 0 5px 1px #ccc;

:deep(.el-image__inner) {

transition: all 0.3s;

cursor: pointer;

&:hover {

transform: scale(1.2);

}

}

:deep(.image-slot) {

display: flex;

justify-content: center;

align-items: center;

width: 100%;

height: 100%;

color: #909399;

font-size: 30px;

}

}

</style>

后端拦截器:

ProfileInterceptorConfig.java

package com.fuel.framework.config;

import com.fuel.framework.interceptor.ProfileInterceptor;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**

* 通用配置

*

* @author hhxx

*/

@Configuration

public class ProfileInterceptorConfig implements WebMvcConfigurer

{

@Autowired

private ProfileInterceptor profileInterceptor;

/**

* 自定义拦截规则

*/

@Override

public void addInterceptors(InterceptorRegistry registry)

{

registry.addInterceptor(profileInterceptor)

.addPathPatterns("/profile/**");

}

}

ProfileInterceptor.java

package com.fuel.framework.interceptor;

import com.alibaba.fastjson2.JSON;

import com.fuel.common.constant.HttpStatus;

import com.fuel.common.core.domain.AjaxResult;

import com.fuel.common.core.domain.model.LoginUser;

import com.fuel.common.utils.ServletUtils;

import com.fuel.common.utils.StringUtils;

import com.fuel.common.utils.ip.AddressUtils;

import com.fuel.common.utils.ip.IpUtils;

import com.fuel.common.utils.spring.SpringUtils;

import com.fuel.framework.security.handle.AuthenticationEntryPointImpl;

import com.fuel.framework.web.service.TokenService;

import eu.bitwalker.useragentutils.UserAgent;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.stereotype.Component;

import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.util.Map;

@Component

public class ProfileInterceptor implements HandlerInterceptor {

@Override

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception

{

//获取token

String token = request.getParameter("token");

// 获取用户代理

UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));

// 获取ip

String ipaddr = IpUtils.getIpAddr(ServletUtils.getRequest());

// 获取登录地点

String loginLocation = AddressUtils.getRealAddressByIP(ipaddr);

// 获取浏览器

String browser = userAgent.getBrowser().getName();

// 获取操作系统

String os = userAgent.getOperatingSystem().getName();

TokenService bean = SpringUtils.getBean(TokenService.class);

AuthenticationEntryPointImpl authenticationEntryPointImpl = SpringUtils.getBean(AuthenticationEntryPointImpl.class);

// 校验token是否有效

Map<String, Object> stringObjectMap = bean.verifyToken(token);

boolean bl = false;

if (stringObjectMap.size() > 0) {

// 获取登录信息

LoginUser user = (LoginUser) stringObjectMap.get("user");

// 判断是否同一台电脑、同一浏览器、同一操作系统、同一登录地点

if (user != null && ipaddr.equals(user.getIpaddr()) && loginLocation.equals(user.getLoginLocation()) && browser.equals(user.getBrowser()) && os.equals(user.getOs())) {

bl = true;

}

}

if(!bl){

// 校验不通过时返回错误信息--复用Spring Security框架的信息

authenticationEntryPointImpl.commence(request, response, null);

}

return bl;

}

}

TokenService.java

package com.fuel.framework.web.service;

import java.util.HashMap;

import java.util.Map;

import java.util.concurrent.TimeUnit;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson2.JSONArray;

import com.alibaba.fastjson2.JSONObject;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.stereotype.Component;

import com.auth0.jwt.exceptions.JWTVerificationException;

import com.auth0.jwt.exceptions.TokenExpiredException;

import com.fuel.common.constant.Constants;

import com.fuel.common.core.domain.AjaxResult;

import com.fuel.common.core.domain.model.LoginUser;

import com.fuel.common.core.redis.RedisCache;

import com.fuel.common.utils.MessageUtils;

import com.fuel.common.utils.ServletUtils;

import com.fuel.common.utils.StringUtils;

import com.fuel.common.utils.http.HttpUtils;

import com.fuel.common.utils.ip.AddressUtils;

import com.fuel.common.utils.ip.IpUtils;

import com.fuel.common.utils.uuid.IdUtils;

import eu.bitwalker.useragentutils.UserAgent;

import io.jsonwebtoken.Claims;

import io.jsonwebtoken.ExpiredJwtException;

import io.jsonwebtoken.Jwts;

import io.jsonwebtoken.SignatureAlgorithm;

/**

* token验证处理

*

* @author hhxx

*/

@Component

public class TokenService

{

// 令牌自定义标识

@Value("${token.header}")

private String header;

// 令牌秘钥

@Value("${token.secret}")

private String secret;

// 令牌有效期(默认30分钟)

@Value("${token.expireTime}")

private int expireTime;

protected static final long MILLIS_SECOND = 1000;

protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;

private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;

@Autowired

private RedisCache redisCache;

/***

* 验证令牌

* @param token

* @return

*/

public Map<String,Object> verifyToken(String token) {

Map<String,Object> resultMap = new HashMap<>();

boolean bl = true;

try {

Claims claims = parseToken(token);

// 解析对应的权限以及用户信息

String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);

String userKey = getTokenKey(uuid);

LoginUser user = JSONObject.parseObject(redisCache.getCacheObject(userKey),LoginUser.class);

if(user != null) {

bl = true;

resultMap.put("bl", bl);

}else {

bl = false;

resultMap.put("bl", bl);

resultMap.put("msg", "token已过期");

}

}catch (ExpiredJwtException eje) {

bl = false;

resultMap.put("bl", bl);

resultMap.put("msg", "token已过期");

}

catch(Exception ex) {

bl = false;

resultMap.put("bl", bl);

resultMap.put("msg", "token验证异常");

}

return resultMap;

}

}



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。