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

Rails后端+KotlinJs Ktor前端DeviseJWT认证实现求助

解决Devise JWT认证的Ktor前端问题

一、实现Ktor中类似Fetch API credentials: include 的Cookie保存逻辑

Kotlin/JS的Ktor要处理跨域Cookie,需在请求配置中开启凭证包含,并配合后端CORS设置:

  • 配置Ktor HttpClient,启用Cookie存储并在请求中指定凭证规则:
    val client = HttpClient {
        install(HttpCookies) {
            storage = AcceptAllCookiesStorage() // 自动存储所有Cookie
        }
        install(ContentNegotiation) {
            json()
        }
    }
    
    // 登录请求示例
    val response = client.post("http://your-rails-api.com/users/sign_in") {
        contentType(ContentType.Application.Json)
        setBody(mapOf("user" to mapOf("email" to "test@example.com", "password" to "password123")))
        // 对应Fetch的credentials: include,允许携带和接收Cookie
        credentials(HttpCredentials.Include)
    }
    
  • Rails后端必须配置CORS允许凭证:
    修改config/initializers/cors.rb,确保开启credentials: true并指定前端域名:
    Rails.application.config.middleware.insert_before 0, Rack::Cors do
      allow do
        origins 'http://your-ktor-frontend-domain.com' # 替换为实际前端域名
        resource '*',
          headers: :any,
          methods: [:get, :post, :put, :patch, :delete, :options, :head],
          credentials: true
      end
    end
    
  • 补充Devise JWT的Cookie存储配置(若用Cookie存token):
    在config/initializers/devise.rb中添加:
    config.jwt do |jwt|
      jwt.token_store = :cookie
      jwt.cookie_options = { secure: Rails.env.production?, httponly: true, same_site: :lax }
      # 保留原有dispatch_requests、revocation_requests、secret_key配置
    end
    

二、通过返回体传递JWT Token的实现方式

虽然这种方式存在XSS风险,但具体实现如下:

Rails后端修改

  • 自定义会话控制器,将JWT Token写入响应体:
    1. 生成控制器文件:
      rails generate controller sessions
      
    2. 编写控制器逻辑,继承Devise SessionsController:
      class SessionsController < Devise::SessionsController
        def create
          super do |resource|
            # 生成JWT Token
            token = Warden::JWTAuth::UserEncoder.new.call(resource, :user, nil).first
            # 将token放入响应JSON
            render json: { user: resource, jwt_token: token }, status: :ok and return
          end
        end
      end
      
    3. 替换Devise默认路由:
      在config/routes.rb中修改:
      devise_for :users, controllers: { sessions: 'sessions' }
      

Ktor前端处理

  • 提取响应体中的token并存储,后续请求携带:
    data class LoginResponse(val user: User, val jwt_token: String)
    
    // 登录请求
    val response = client.post<LoginResponse>("http://your-rails-api.com/users/sign_in") {
        contentType(ContentType.Application.Json)
        setBody(mapOf("user" to mapOf("email" to "test@example.com", "password" to "password123")))
    }
    
    // 存储token到localStorage
    window.localStorage.setItem("jwt_token", response.jwt_token)
    
    // 后续接口请求携带token
    val protectedResponse = client.get("http://your-rails-api.com/protected_resource") {
        headers {
            append(HttpHeaders.Authorization, "Bearer ${window.localStorage.getItem("jwt_token")}")
        }
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 08:35:11