Clojure服务与React Native通信出现Error 403问题如何解决?
解决Clojure服务与React Native Axios通信的403错误问题
问题背景
我在localhost:3000运行一个Clojure服务,React Native客户端用Axios调用/api/invest接口时收到403错误,而且服务端featured/invest函数里的日志完全没输出,说明请求根本没到达业务处理逻辑。
错误原因分析
- CSRF保护拦截请求:服务端路由配置里给根路径
""加了middleware/wrap-csrf中间件,这个中间件会验证请求中的CSRF token。但React Native是原生APP,不是浏览器环境,没法自动获取并携带Cookie里的CSRF token,所以请求直接被拦截返回403。 - 路由请求方法不匹配:客户端用
axios.post发送POST请求,但服务端路由里的/api/invest没有明确指定请求方法,Reitit默认会匹配GET请求——不过这里因为CSRF先拦截了,所以先出现403错误。 - CORS预检请求未处理:React Native跨域请求会先发送OPTIONS预检请求,当前服务端只有在
invest函数返回时才带CORS头,但OPTIONS请求根本没走到这个函数,预检失败也会间接导致请求异常。
具体解决方案
1. 给API路由禁用CSRF保护
API接口通常使用Token认证,不需要CSRF保护,我们可以把/api路径的中间件单独配置,去掉CSRF:
修改服务端路由代码:
(defn home-routes [] ["" {:middleware [middleware/wrap-csrf middleware/wrap-formats]} ["/" {:get home-page}] ; 单独给/api配置中间件,移除wrap-csrf ["/api" {:middleware [middleware/wrap-formats]} ["/about" {:get about-page}] ["/featured" {:get featured/get-featured}] ; 明确请求方法 ["/invest" {:post featured/invest}] ; 明确指定POST方法,匹配客户端请求 ] ])
2. 全局处理CORS跨域
使用ring-cors库统一处理跨域请求,包括OPTIONS预检请求:
- 首先在
project.clj里添加依赖:[ring-cors "0.1.13"] - 然后在
humboiserver.middleware里添加CORS中间件:(ns humboiserver.middleware (:require [ring.middleware.cors :refer [wrap-cors]] ; 保留其他原有依赖 )) ; 新增CORS中间件配置(开发环境宽松设置,生产环境需限制来源) (defn wrap-cors [handler] (wrap-cors handler :access-control-allow-origin [#".*"] :access-control-allow-methods [:get :post :put :delete :options] :access-control-allow-headers ["Content-Type"])) - 最后在服务端入口(比如
handler.clj)把wrap-cors添加到中间件链最前面,确保所有请求都经过CORS处理。
3. 修复客户端Axios调用的问题
- 给URL加上
http://前缀,Axios需要完整的HTTP地址; - 因为是
async函数,要加await获取实际响应对象,不然res是Promise,无法直接取res.data:
修改客户端代码:
export const invest = (itemid, amount) => async dispatch => { console.log("investing in actions") const domain = 'http://localhost:3000' const res = await axios.post(domain + '/api/invest', {itemid: itemid, amount: amount}); console.log("response is", res) dispatch({ type: INVESTED, payload: res.data}); }
验证修改
做完以上修改后,重启Clojure服务,再测试React Native客户端的调用:
- 服务端
invest函数里的prn "invested"应该能正常打印日志; - 客户端应该能收到200响应,不再返回403错误。
内容的提问来源于stack exchange,提问作者zendevil
相关产品推荐
相关产品推荐

