You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React Native WebView中保持Django Web会话持续有效?

React Native WebView iOS端保留Django会话的解决方案

问题背景

参照相关方案实现iOS端WebView会话保留后,重启应用仍出现会话失效问题。当前已尝试在请求中回传Cookie,但因使用Django会话机制,存在适配问题。以下是现有实现代码、Cookie字符串及浏览器请求响应头信息:

现有实现代码

export default class App extends Component {
    constructor(props) {
        super(props);
        this.currentUrl = '';
        this.myWebView = React.createRef();
        this.state = {
            isReady: false,
            cookiesString: '',
            userAgent: '',
        };
    }

    UNSAFE_componentWillMount() {
        // CookieManager.clearAll();
        this.provideMeSavedCookies()
            .then(async (savedCookies) => {
                let cookiesString = this.jsonCookiesToCookieString(savedCookies);
                const sessionid = await AsyncStorage.getItem('sessionid');
                if (sessionid) {
                    cookiesString += `sessionid=${sessionid};`;
                }
                DeviceInfo.getUserAgent().then((userAgent) => {
                    this.setState({userAgent: userAgent, cookiesString, isReady: true});
                });
            })
            .catch((e) => {
                this.setState({isReady: true});
            });
    }

    onLoadEnd = () => {
        let successUrl = `${domain}`;
        if (this.currentUrl === successUrl) {
            CookieManager.getAll().then((res) => {
                console.log('RES');
                console.log(res)
                AsyncStorage.setItem('savedCookies', JSON.stringify(res));
                if (res.sessionid) {
                    AsyncStorage.setItem('sessionid', res.sessionid.value);
                }
            });
        }
    };

    jsonCookiesToCookieString = (json) => {
        let cookiesString = '';
        for (let [key, value] of Object.entries(json)) {
            cookiesString += `${key}=${value.value}; `;
        }
        return cookiesString;
    };

    onNavigationStateChange = (navState) => {
        this.currentUrl = navState.url;
    };


    provideMeSavedCookies = async () => {
        try {
            let value = await AsyncStorage.getItem('savedCookies');
            if (value !== null) {
                return Promise.resolve(JSON.parse(value));
            }
        } catch (error) {
            return {}
        }
    };

    render() {
        const {userAgent, cookiesString, isReady} = this.state;
        return (
            <SafeAreaView style={{ flex:1 }}>
                {isReady && <WebView
                    ref={this.myWebView}
                    source={{
                        uri: `${domain}`,
                        headers: {
                            'Cookie': cookiesString,
                            'Connection': 'keep-alive',
                            'Cache-Control': 'max-age=0',
                            'User-Agent': userAgent
                        },
                    }}
                    useWebView2={true} // this is just to test
                    cacheEnabled={false}
                    incognito={false}
                    scalesPageToFit
                    useWebKit
                    onLoadEnd={this.onLoadEnd}
                    onNavigationStateChange={this.onNavigationStateChange}
                    sharedCookiesEnabled
                    javaScriptEnabled={true}
                    domStorageEnabled={true}

                />}
                {!isReady &&
                    <View><Text>Loading...</Text></View>
                }
            </SafeAreaView>
        );
    }
}

当前生成的Cookie字符串

csrftoken=6dkeV4w5qcUbAnM1IvUoIt7EhZVScsSbj4bkWHJLRXQWyk3zy40eSREqaeE0mpaT; sessionid=x2x65ksaz9k9izw756vnie4dmlgdx1zk; sessionid=x2x65ksaz9k9izw756vnie4dmlgdx1zk;

PC浏览器请求响应头

请求响应头截图

问题分析

  1. Cookie格式错误:手动拼接的Cookie字符串重复添加了sessionid,且未包含Django会话Cookie必需的域、路径、HttpOnly等属性,导致WebView无法正确识别。
  2. Cookie传递方式不当:直接通过请求头传递Cookie,无法被iOS WebKit的CookieJar持久化存储,重启App后WebView无法读取到有效会话信息。
  3. CSRF与会话关联缺失:Django的CSRF Token与会话绑定,仅传递Cookie键值对无法满足后端的验证逻辑。

修正方案

1. 改用CookieManager直接设置完整Cookie

放弃手动拼接Cookie字符串,通过CookieManager将保存的完整Cookie对象设置到WebView的CookieJar中,确保属性与Django返回一致:

UNSAFE_componentWillMount() {
  this.provideMeSavedCookies()
    .then(async (savedCookies) => {
      const domainHost = domain.replace('https://', '').replace('http://', '');
      // 恢复保存的完整Cookie
      if (savedCookies && Object.keys(savedCookies).length > 0) {
        await CookieManager.setFromResponse(domain, savedCookies);
      }
      // 单独确保sessionid的属性正确
      const sessionid = await AsyncStorage.getItem('sessionid');
      if (sessionid) {
        await CookieManager.set({
          name: 'sessionid',
          value: sessionid,
          domain: domainHost,
          path: '/',
          secure: domain.startsWith('https://'),
          httpOnly: true,
        });
      }
      DeviceInfo.getUserAgent().then((userAgent) => {
        this.setState({userAgent, isReady: true});
      });
    })
    .catch((e) => {
      this.setState({isReady: true});
    });
}

2. 保存完整的Cookie属性

在onLoadEnd中获取包含所有属性的Cookie对象并保存,避免丢失域、路径等关键信息:

onLoadEnd = () => {
  let successUrl = `${domain}`;
  if (this.currentUrl === successUrl) {
    // 获取包含完整属性的Cookie
    CookieManager.getAll(true)
      .then((res) => {
        console.log('完整Cookie信息:', res);
        AsyncStorage.setItem('savedCookies', JSON.stringify(res));
        if (res.sessionid) {
          AsyncStorage.setItem('sessionid', res.sessionid.value);
        }
      });
  }
};

3. 移除请求头中的手动Cookie字段

通过CookieManager设置Cookie后,WebView会自动在请求中携带Cookie,无需手动添加,避免冲突:

source={{
  uri: `${domain}`,
  headers: {
    'Connection': 'keep-alive',
    'Cache-Control': 'max-age=0',
    'User-Agent': userAgent
  },
}}

4. 对齐Django后端配置

  • 确保Django的SESSION_COOKIE_DOMAIN设置与App请求的域名一致。
  • 如果使用HTTPS,确认SESSION_COOKIE_SECURE = True,与App中设置的Cookiesecure属性匹配。
  • 保持SESSION_COOKIE_HTTPONLY = True,这是Django默认设置,确保会话Cookie的安全性。

关键注意事项

  • iOS中HttpOnly类型的Cookie无法通过JavaScript读取,但react-native-cookies库可以获取到,需确保使用该库进行Cookie管理。
  • 保持WebView的sharedCookiesEnabled属性开启,确保App与WebView的CookieJar共享。

内容的提问来源于stack exchange,提问作者Prabhakaran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 09:35:11