diff --git a/admin-web/src/utils/cache.js b/admin-web/src/utils/cache.js index 06b99c0b1..b24074b6a 100644 --- a/admin-web/src/utils/cache.js +++ b/admin-web/src/utils/cache.js @@ -39,4 +39,4 @@ function getLocalStorage(key) { } catch (e) { throw new Error(`localStorage 获取错误! ${e}`); } -} +} \ No newline at end of file diff --git a/common/common-framework/src/main/java/cn/iocoder/common/framework/servlet/CorsFilter.java b/common/common-framework/src/main/java/cn/iocoder/common/framework/servlet/CorsFilter.java new file mode 100644 index 000000000..1080f4816 --- /dev/null +++ b/common/common-framework/src/main/java/cn/iocoder/common/framework/servlet/CorsFilter.java @@ -0,0 +1,35 @@ +package cn.iocoder.common.framework.servlet; + +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class CorsFilter implements Filter { + + @Override + public void init(FilterConfig filterConfig) { } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + HttpServletResponse resp = (HttpServletResponse) response; + resp.setHeader("Access-Control-Allow-Origin", "*"); + resp.setHeader("Access-Control-Allow-Methods", "*"); + resp.setHeader("Access-Control-Allow-Headers", "*"); + resp.setHeader("Access-Control-Max-Age", "1800"); + // For HTTP OPTIONS verb/method reply with ACCEPTED status code -- per CORS handshake + // 例如说,vue axios 请求时,会自带该逻辑的 + HttpServletRequest req = (HttpServletRequest) request; + if (req.getMethod().equals("OPTIONS")) { + resp.setStatus(HttpServletResponse.SC_ACCEPTED); + return; + } + // 如果是其它请求方法,则继续过滤器。 + chain.doFilter(request, response); + } + + @Override + public void destroy() { + } + +} \ No newline at end of file diff --git a/mobile-web/src/api/user.js b/mobile-web/src/api/user.js index 75c1e5b0a..78cfb1029 100644 --- a/mobile-web/src/api/user.js +++ b/mobile-web/src/api/user.js @@ -71,5 +71,33 @@ export function ExchangeCoupon(code){ }) } +export function getUserInfo() { + return request({ + url: 'user-api/users/user/info', + method: 'get', + headers: { + test: 1, + } + }); +} - \ No newline at end of file +export function doPassportMobileRegister(mobile, code) { + return request({ + url: 'user-api/users/passport/mobile/register', + method: 'post', + params: { + mobile, + code, + } + }); +} + +export function doPassportMobileSendRegisterCode(mobile) { + return request({ + url: 'user-api/users/passport/mobile/send_register_code', + method: 'post', + params: { + mobile, + } + }); +} \ No newline at end of file diff --git a/mobile-web/src/config/env.js b/mobile-web/src/config/env.js index ccb3d3d61..1ac66ee86 100644 --- a/mobile-web/src/config/env.js +++ b/mobile-web/src/config/env.js @@ -18,6 +18,10 @@ if (process.env.NODE_ENV == 'development') { baseUrl = ''; } +baseUrl = 'http://127.0.0.1'; +dataSources = 'remote'; +// dataSources = 'local'; + export { baseUrl, routerMode, diff --git a/mobile-web/src/config/request.js b/mobile-web/src/config/request.js index f52ad525c..ed8c6e2f9 100644 --- a/mobile-web/src/config/request.js +++ b/mobile-web/src/config/request.js @@ -1,11 +1,14 @@ import axios from 'axios' import {baseUrl, dataSources} from './env'; import datas from '../data/data'; - +import { getAccessToken } from '../utils/cache.js'; const service = axios.create({ baseURL: baseUrl, // api 的 base_url timeout: 5000, // request timeout + headers: { + 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' + } }); const servicef = function (parameter) { @@ -21,6 +24,15 @@ const servicef = function (parameter) { }) return promist; } + // 设置 access token + // debugger; + // if (getAccessToken()) { + // parameter.headers = { + // ...parameter.headers, + // 'Authorization': `Bearer ${getAccessToken()}`, + // }; + // } + // debugger; return service(parameter); } @@ -33,6 +45,11 @@ service.interceptors.request.use( // config.headers['X-Token'] = getToken() // } + debugger; + if (getAccessToken()) { + config.headers['Authorization'] = `Bearer ${getAccessToken()}`; + } + return config }, error => { diff --git a/mobile-web/src/page/user/index.vue b/mobile-web/src/page/user/index.vue index bddba96ed..1ededdbae 100644 --- a/mobile-web/src/page/user/index.vue +++ b/mobile-web/src/page/user/index.vue @@ -82,21 +82,32 @@ diff --git a/mobile-web/src/page/user/info/detail.vue b/mobile-web/src/page/user/info/detail.vue index 804745a90..d74862bfd 100644 --- a/mobile-web/src/page/user/info/detail.vue +++ b/mobile-web/src/page/user/info/detail.vue @@ -3,10 +3,10 @@ - - - - + + + + @@ -19,4 +19,4 @@ export default { + \ No newline at end of file diff --git a/mobile-web/src/utils/cache.js b/mobile-web/src/utils/cache.js new file mode 100644 index 000000000..b9539a17c --- /dev/null +++ b/mobile-web/src/utils/cache.js @@ -0,0 +1,46 @@ +/* eslint-disable */ + +// localStorage 操作 + +const cacheKeys = { + accessTokenKey: 'accessToken', + refreshTokenKey: 'refreshToken', +}; + +/// +/// 设置 loginToken,分为 accessToken 和 refreshToken + +export function setLoginToken(accessToken, refreshToken) { + setLocalStorage(cacheKeys.accessTokenKey, accessToken); + setLocalStorage(cacheKeys.refreshTokenKey, refreshToken); +} + +export function getLoginToken() { + const res = {}; + res[cacheKeys.accessTokenKey] = getLocalStorage(cacheKeys.accessTokenKey); + res[cacheKeys.refreshTokenKey] = getLocalStorage(cacheKeys.refreshTokenKey); + return res; +} + +export function getAccessToken() { + return getLocalStorage(cacheKeys.accessTokenKey); +} + +/// +/// 设置 localStorage 公共方法 + +function setLocalStorage(key, value) { + try { + localStorage.setItem(key, value); + } catch (e) { + throw new Error(`localStorage 设置错误! ${e}`); + } +} + +function getLocalStorage(key) { + try { + return localStorage.getItem(key); + } catch (e) { + throw new Error(`localStorage 获取错误! ${e}`); + } +} \ No newline at end of file diff --git a/user/user-application/src/main/java/cn/iocoder/mall/user/application/config/MVCConfiguration.java b/user/user-application/src/main/java/cn/iocoder/mall/user/application/config/MVCConfiguration.java index 23e561992..cf5a62d16 100644 --- a/user/user-application/src/main/java/cn/iocoder/mall/user/application/config/MVCConfiguration.java +++ b/user/user-application/src/main/java/cn/iocoder/mall/user/application/config/MVCConfiguration.java @@ -1,16 +1,16 @@ package cn.iocoder.mall.user.application.config; import cn.iocoder.common.framework.config.GlobalExceptionHandler; +import cn.iocoder.common.framework.servlet.CorsFilter; import cn.iocoder.mall.admin.sdk.interceptor.AdminSecurityInterceptor; import cn.iocoder.mall.user.sdk.interceptor.UserAccessLogInterceptor; import cn.iocoder.mall.user.sdk.interceptor.UserSecurityInterceptor; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; -import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.config.annotation.*; @EnableWebMvc @Configuration @@ -27,6 +27,7 @@ public class MVCConfiguration implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { + // CORS // 用户 registry.addInterceptor(userAccessLogInterceptor).addPathPatterns("/users/**"); registry.addInterceptor(userSecurityInterceptor).addPathPatterns("/users/**"); // 只拦截我们定义的接口 @@ -41,4 +42,21 @@ public class MVCConfiguration implements WebMvcConfigurer { registry.addResourceHandler("webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); } + // TODO 芋艿,允许跨域 +// @Override +// public void addCorsMappings(CorsRegistry registry) { +// registry.addMapping("/**") +// .allowedHeaders("*") +// .allowedMethods("*") +// .allowedOrigins("*"); +// } + + @Bean + public FilterRegistrationBean corsFilter() { + FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); + registrationBean.setFilter(new CorsFilter()); + registrationBean.addUrlPatterns("/*"); + return registrationBean; + } + } \ No newline at end of file diff --git a/user/user-sdk/src/main/java/cn/iocoder/mall/user/sdk/interceptor/UserAccessLogInterceptor.java b/user/user-sdk/src/main/java/cn/iocoder/mall/user/sdk/interceptor/UserAccessLogInterceptor.java index c52646fcf..a13c61e86 100644 --- a/user/user-sdk/src/main/java/cn/iocoder/mall/user/sdk/interceptor/UserAccessLogInterceptor.java +++ b/user/user-sdk/src/main/java/cn/iocoder/mall/user/sdk/interceptor/UserAccessLogInterceptor.java @@ -8,6 +8,7 @@ import com.alibaba.fastjson.JSON; import org.apache.commons.lang3.exception.ExceptionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.http.HttpMethod; import org.springframework.stereotype.Component; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; @@ -37,6 +38,11 @@ public class UserAccessLogInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { + // TODO 芋艿,临时拿来处理 vue axios options 请求的问题。 + if (HttpMethod.OPTIONS.matches(request.getMethod())) { + + return false; // 通过这样的方式,让前端知道允许的 header 等等。 + } // 记录当前时间 START_TIME.set(new Date()); return true;