我的项目的前端和后端托管在单独的域中。当用户注册帐户时,会将cookie从服务器设置到包含userId的客户端计算机上。这在Google chrome和Firefox中没有问题,但是除非启用了第三方Cookie,否则在Safari上将无法工作。请求是通过阿波罗发送的,后端有一个graphql Yoga服务器。这是当前的配置:
前端:
import { ApolloLink, Observable, split } from 'apollo-link';
import { ApolloClient } from 'apollo-client';
import { BatchHttpLink } from 'apollo-link-batch-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { WebSocketLink } from 'apollo-link-ws';
import { createPersistedQueryLink } from 'apollo-link-persisted-queries';
import { getMainDefinition } from 'apollo-utilities';
import { onError } from 'apollo-link-error';
import withApollo from 'next-with-apollo';
import { withClientState } from 'apollo-link-state';
import { wss, endpoint } from '../config';
function createClient({ headers }) {
const cache = new InMemoryCache();
const request = async operation => {
operation.setContext({
http: {
includeExtensions: true,
includeQuery: false,
},
fetchOptions: {
credentials: 'include',
},
headers,
});
};
const requestLink = new ApolloLink(
(operation, forward) =>
new Observable(observer => {
let handle;
Promise.resolve(operation)
.then(oper => request(oper))
.then(() => {
handle = forward(operation).subscribe({
next: observer.next.bind(observer),
error: observer.error.bind(observer),
complete: observer.complete.bind(observer),
});
})
.catch(observer.error.bind(observer));
return () => {
if (handle) handle.unsubscribe();
};
})
);
const httpLink = new BatchHttpLink({
uri: endpoint,
});
const wsLink = process.browser
? new WebSocketLink({
uri: wss,
options: {
reconnect: true,
},
})
: () => {
console.log('SSR');
};
const terminatingLink = split(
({ query }) => {
const { kind, operation } = getMainDefinition(query);
return (
kind === 'OperationDefinition' &&
operation === 'subscription' &&
process.browser
);
},
wsLink,
httpLink
);
return new ApolloClient({
link: ApolloLink.from([
onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors) {
console.error({ graphQLErrors });
}
if (networkError) {
console.error({ networkError });
}
}),
requestLink,
withClientState({
defaults: {
isConnected: true,
},
resolvers: {
Mutation: {
updateNetworkStatus: (_, { isConnected }, { cache }) => {
cache.writeData({ data: { isConnected } });
return null;
},
},
},
cache,
}),
createPersistedQueryLink().concat(terminatingLink),
]),
cache,
});
}
export default withApollo(createClient);
后端:
const cookieParser = require('cookie-parser');
const jwt = require('jsonwebtoken');
require('dotenv').config({ path: 'variables.env' });
const createServer = require('./createServer');
const db = require('./db');
const server = createServer();
server.express.use(cookieParser());
server.express.use((req, res, next) => {
const { token } = req.cookies;
if (token) {
const { userId } = jwt.verify(token, process.env.APP_SECRET);
req.userId = userId;
}
next();
});
server.express.use(async (req, res, next) => {
if (!req.userId) return next();
const user = await db.query.user(
{ where: { id: req.userId } },
'{id, firstName, lastName, email}'
);
req.user = user;
next();
});
server.start(
{
cors: {
credentials: true,
origin: process.env.FRONTEND_URL,
},
subscriptions: {
keepAlive: true,
},
},
s => {
console.log('Server running!');
}
);
从我看到的两端都设置了凭据的角度来看,请求以cookie响应,但Safari不会设置它。
Request Method: POST
Status Code: 200 OK
Remote Address: 10.22.179.204:80
Referrer Policy: no-referrer-when-downgrade
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://www.rideout.rocks
Connection: keep-alive
Content-Length: 129
Content-Type: application/json
Date: Tue, 13 Aug 2019 10:17:07 GMT
Server: Cowboy
Vary: Origin
Via: 1.1 vegur
X-Powered-By: Express
Provisional headers are shown
accept: */*
content-type: application/json
Referer: https://www.rideout.rocks/
Sec-Fetch-Mode: cors
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36
Request URL: https://rideout-app-backend.herokuapp.com/
Request Method: POST
Status Code: 200 OK
Remote Address: 10.22.179.204:80
Referrer Policy: no-referrer-when-downgrade
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://www.rideout.rocks
Connection: keep-alive
Content-Length: 537
Content-Type: application/json
Date: Tue, 13 Aug 2019 10:17:07 GMT
Server: Cowboy
Vary: Origin
Via: 1.1 vegur
X-Powered-By: Express
Provisional headers are shown
accept: */*
content-type: application/json
Referer: https://www.rideout.rocks/
Sec-Fetch-Mode: cors
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36```
Thanks for any insight and help.