이 글은 주로 쿠키를 시뮬레이션하기 위한 WeChat 미니 프로그램의 구현을 소개합니다. 내용이 꽤 좋아서 지금 공유하고 참고하겠습니다.
개발 배경
기존 시스템에는 이미 완전한 인터페이스 세트가 있으며, 사용자 상태 및 확인은 모두 쿠키를 기반으로 합니다.
일부 비즈니스에서는 미니 프로그램 버전을 사용해야 합니다. 우리 모두 알고 있듯이 WeChat 미니 프로그램은 쿠키를 지원하지 않습니다. 온라인으로 비즈니스를 시작하는 가장 좋은 방법은 기존 인터페이스 세트를 기반으로 하는 것입니다. 이는 크게 변하지 않으며 가장 빠릅니다.
쿠키 시뮬레이션
브라우저의 개발 도구와 네트워크 표시줄을 통해 요청을 확인하세요. 브라우저의 쿠키는 쿠키를 키 이름으로 사용하여 각 http의 요청 헤더에 전달됩니다.
그런 다음 WeChat의 공식 요청 메소드 wx.request에서 헤더를 설정하고 시뮬레이션할 수 있는 쿠키를 추가합니다.
서버에서 쿠키를 반환하는 방법에 대한 질문이 다시 발생합니다.
로그인 인터페이스를 통해 http 반환 헤더를 봅니다(로그인할 때 서버는 쿠키를 세션으로 이식합니다).
wx.request({ url: '/api/login', success: (data) => { if(data.statusCode === 200) { console.log(data); // data 中应该会有 Set-Cookie 或 set-cookie 的字样,嗯,那就是服务器种下的 cookie } } })
쿠키를 가져와 로컬에 저장하고 다음에 데이터를 요청할 때 직접 삽입하면 완벽합니다.
쿠키 포맷하기
원래는 쿠키를 입력하고 종료하는 것만으로 완벽하게 시뮬레이션할 수 있다고 생각했는데, 실제 동작을 해보니 쿠키 서버가 이를 인식하지 못하는 것을 발견했습니다.
서버에서 반환된 쿠키에는 path=/;
// 服务器放回的 cookie let cookie = 'userKey=1234567890; Path=/; Expires=Thu, 21 Jun 2018 13:15:08 GMT; HttpOnly,userId=111; Path=/; Expires=Thu, 21 Jun 2018 13:15:08 GMT,nickName=; Path=/; Expires=Thu, 21 Jun 2018 13:15:08 GMT,userName=111111; Path=/; Expires=Thu, 21 Jun 2018 13:15:08 GMT,imgUrl=; Path=/; Expires=Thu, 21 Jun 2018 13:15:08 GMT'; // 模拟的是需要的格式样式 let virtualCookie = 'userKey=1234567890; userName=111111; userId=111;';
맙소사~필터링 방법과 같은 저장을 위한 많은 필드가 포함됩니다.
간단하고 대략적인 필터링 솔루션을 작성했습니다.
// cookie 的本地存储位置 const COOKIE_KEY = '__cookie_key__'; /** * 格式化用户需要的 cookie */ const normalizeUserCookie = (cookies = '') => { let __cookies = []; (cookies.match(/([\w\-.]*)=([^\s=]+);/g) || []).forEach((str) => { if (str !== 'Path=/;' && str.indexOf('csrfToken=') !== 0) { __cookies.push(str); } }); wx.setStorageSync(COOKIE_KEY, __cookies.join(' ')); };
csrfToken
은 다음으로 Egg.js
와 함께 사용되며, Path=/;
는 일부 애플리케이션에서 사용됩니다. path=/;
csrfToken
是接下来配合 Egg.js
用的,Path=/;
在某些应用下会是 path=/;
normalizeUserCookie
主要是过滤了 xx=xxx
; 这样的数据,然后排除 path=/;
这样无意义的数据。
在登录接口的时候,存上 cookie,在接下来的请求中带上,那么,应该、没错、可能、可以模拟了。
配合 Egg.js
Egg 内置的 egg-security
插件默认对所有『非安全』的方法,例如 POST,PUT,DELETE 都进行 CSRF 校验。
Egg.js 虽然可以在配置中关闭 CSRF,但是,如果一定要使用呢?
首先,要弄明白一件事,csrfToken
怎么来的。
经过多次验证得知,当 http 请求时,在约定位置没有携带上 csrfToken 值,此次请求会在返回的 cookie 中携带上一个新的 csrfToken;当本次请求已携带上值,就不会产生成 csrfToken。当约定位置带上的 csrfToken 与 cookie 里面的 csrfToken 一致时,通过验证。
接上面的 格式化用户需要的 cookie
操作,先抛开 csrfToken 单独处理用户状态等。
在每次请求结束后,试着单独拿 cookie 中可能存在的 csrfToken,有值就缓存,没值跳过用旧值。
封装一个 Ajax
本次小程序是基于 wepy 的,所以使用了优化后的 wepy.request
normalizeUserCookie
는 주로 xx=xxx
와 같은 데이터를 필터링한 다음 path=/;< /code>를 제외합니다. . <p></p>인터페이스에 로그인할 때 쿠키를 저장하고 다음 요청에 가져오면 아마도 시뮬레이션이 가능할 것입니다. <p></p><p class="jb51code"></p>Egg.js<p></p><p></p><p>Egg에 내장된 <code> egg-security
플러그인은 POST, PUT, 그리고 삭제하세요. Egg.js 구성에서 CSRF를 끌 수 있지만 반드시 사용해야 한다면 어떻게 될까요? 우선 한 가지, csrfToken
이 어떻게 유래되었는지 이해해야 합니다.
많은 검증 끝에 우리는 http 요청이 합의된 위치에 csrfToken 값을 전달하지 않는 경우 이 요청이 이미 값을 전달하면 반환된 쿠키에 새 csrfToken을 전달하며 생성되지 않는다는 것을 알게 되었습니다. csrfToken에. 합의된 위치의 csrfToken이 쿠키의 csrfToken과 일치하면 확인이 통과됩니다.
사용자에게 필요한 위의 형식 쿠키
작업을 계속하고 먼저 csrfToken을 따로 보관하고 사용자 상태만 처리합니다. 각 요청 후에 쿠키에 별도로 존재할 수 있는 csrfToken을 가져오도록 시도하세요. 값이 있으면 캐시하세요. 값이 없으면 건너뛰고 이전 값을 사용하세요.
Ajax를 캡슐화합니다
🎜🎜🎜이 애플릿은 wepy 기반이므로 Egg.js 버전에 최적화된wepy.request
;🎜🎜가 사용됩니다. 🎜🎜실제 전개와 다소 다를 수 있으니 적절하게 수정해주세요. 🎜🎜🎜import wepy from 'wepy'; export const HTTP_HOST = 'http://127.0.0.1:3000'; export const HTTP_HOST_API = `${HTTP_HOST}/api/wxmp`; // cookie 的本地存储位置 const COOKIE_KEY = '__cookie_key__'; // csrfToken 的本地存储位置 const CSRF_TOKEN_KEY = '__csrf_token__'; /** * 清除用户Cookie */ export const cleanUserCookie = () => { wx.setStorageSync(COOKIE_KEY, ''); } /** * 格式化用户需要的 cookie * @param {String} cookies */ export const normalizeUserCookie = (cookies = '') => { let __cookies = []; (cookies.match(/([\w\-.]*)=([^\s=]+);/g) || []).forEach((str) => { if (str !== 'path=/;' && str.indexOf('csrfToken=') !== 0) { __cookies.push(str); } }); wx.setStorageSync(COOKIE_KEY, __cookies); }; /** * 格式化 token */ const normalizeCsrfToken = () => { let __value = wx.getStorageSync(CSRF_TOKEN_KEY) || ''; let __inputs = __value.match(/csrfToken=[\S]*/) || []; let __key = __inputs[0]; // csrfToken=1212132323; if (!!!__key) { return ''; } // 脱水 return __key.replace(/;$/, '').replace(/^csrfToken=/, ''); }; /** * 保存 csrf 的cookie * 不一定每次请求都会更新 cookie * @param {String} cookie */ const seveCsrfTokenCookie = (cookie) => { if (cookie) { wx.setStorageSync(CSRF_TOKEN_KEY, cookie); } }; /** * 请求数据 * @param {Object} opt */ export const doAjax = (opt) => { return new Promise((resolve, reject) => { let Cookies = wx.getStorageSync(COOKIE_KEY) || []; let csrf = normalizeCsrfToken(); let url = opt.url; // 整理 Cookie Cookies.push(`csrfToken=${csrf};`); // 设置请求头部 opt.header = Object.assign( { 'x-csrf-token': csrf, Cookie: Cookies.join(' ') }, opt.header || {} ); opt.success = (data) => { seveCsrfTokenCookie(data.header['set-cookie']); // 统一操作 if (data.statusCode == 200) { if (url === '/login') { normalizeUserCookie(data.header['set-cookie']); } resolve(data.data); } else { reject('未知错误,请重试一次'); } }; opt.fail = (err) => { reject(err); }; opt.url = `${HTTP_HOST_API}${opt.url}`; wepy.request(opt); }); };
위 내용은 WeChat 애플릿 시뮬레이션 쿠키 구현의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!