React Native/Expo中Basic Authorization的btoa()函数替代困惑
btoa() and React Native/Expo for Basic Auth Hey there! I totally get the frustration when something that worked smoothly in Cordova (and browsers) breaks in React Native/Expo—let’s break down why your Base64 results don’t match, and fix that Basic Auth setup once and for all.
The Core Difference: btoa() vs. Most RN/Expo Base64 Libraries
The browser’s btoa() function encodes strings using Latin-1 (ISO-8859-1) character encoding. But almost all Base64 utilities in React Native/Expo (like Expo Crypto or third-party libraries such as base64-js) default to UTF-8 encoding. This is the root cause of your mismatched results!
If your credentials (username/password) include non-ASCII characters (like accents, emojis, or non-Latin scripts), Latin-1 and UTF-8 will convert those characters to completely different byte sequences—and thus different Base64 outputs. Even if you’re using ASCII-only credentials right now, fixing this properly avoids edge cases later.
Solution 1: Use Expo Crypto (Recommended, No Extra Dependencies)
Expo has a built-in expo-crypto module that we can use to replicate btoa()’s exact behavior by first converting our string to a Latin-1 byte array:
import * as Crypto from 'expo-crypto'; // Replicates browser's btoa() behavior in React Native/Expo function btoaRN(str) { // Convert string to a Latin-1 encoded Uint8Array const latin1Bytes = new Uint8Array(str.length); for (let i = 0; i < str.length; i++) { // Latin-1 only uses values 0-255; mod 256 ensures we stay within that range latin1Bytes[i] = str.charCodeAt(i) % 256; } // Encode the byte array to Base64 return Crypto.encodeBase64String(latin1Bytes); } // Use it for Basic Auth const username = "your-username"; const password = "your-password"; const credentials = `${username}:${password}`; const basicAuthHeader = `Basic ${btoaRN(credentials)}`;
Solution 2: Use Third-Party base64-js Library
If you prefer using a standalone library, install base64-js first (npm install base64-js or yarn add base64-js), then use this approach:
import { encode } from 'base64-js'; function btoaRN(str) { const latin1Bytes = new Uint8Array(str.length); for (let i = 0; i < str.length; i++) { latin1Bytes[i] = str.charCodeAt(i) % 256; } return encode(latin1Bytes); } // Same Basic Auth usage as above const credentials = `${username}:${password}`; const basicAuthHeader = `Basic ${btoaRN(credentials)}`;
How to Verify It Works
Test with a string that has non-ASCII characters to confirm. For example:
- Browser
btoa("test:é")returnsdGVzdDpp - Using our
btoaRN()function should return the exact same string, whereas a UTF-8-based Base64 encode would returndGVzdDppw6E=(which is incorrect for Basic Auth).
Why This Matters for Basic Auth
HTTP Basic Auth (per RFC 7617) explicitly requires that the username:password string is encoded using Latin-1. Even if your current credentials are ASCII-only, following this spec ensures your code works for all valid credential formats down the line.
内容的提问来源于stack exchange,提问作者Ferenc Dobó

