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

Clojure Kit中JWT认证中间件失效,如何按需应用路由中间件?

问题解决方案

一、修复wrap-auth中间件不生效问题

你的/auth/checked无需携带Authorization头即可访问,核心原因是中间件配置存在两个问题:

  1. 未指定JWT认证方案:默认JWS后端不会自动解析Bearer格式的Authorization头,需显式配置;
  2. 授权逻辑缺失:wrap-authorization依赖明确的权限校验规则,否则不会拦截未认证请求。

修改后的wrap-auth实现:

(require '[buddy.auth.backends.jws :as backends]
         '[buddy.auth.middleware :as auth-middleware]
         '[buddy.auth.accessrules :as accessrules])

(defn wrap-auth [handler]
  (let [backend (backends/jws {:secret "topsecret"
                               :token-name "Bearer"})] ; 指定Bearer认证方案
    (-> handler
        (auth-middleware/wrap-authentication backend)
        ; 添加基础认证校验规则:必须存在身份信息
        (accessrules/wrap-accessrules {:rules [{:pattern #"^/auth/checked"
                                                :handler (fn [req]
                                                           (or (:identity req)
                                                               {:status 401
                                                                :body "Unauthorized"}))}]})
        (auth-middleware/wrap-authorization backend))))

如果不需要复杂权限规则,也可以直接在handler内判断身份:

(defn checked [req]
  (if (:identity req)
    {:status 200 :body "Authenticated"}
    {:status 401 :body "Unauthorized"}))

二、为部分路由应用中间件的三种方式

基于Clojure Kit默认的Reitit路由库,有三种常用的局部路由中间件应用方式:

1. 单个路由Handler包装

直接为目标路由的Handler包装中间件,适合单个路由场景:

(defn api-routes [_opts]
  ["/auth/login" {:post auth/login}]
  ["/auth/checked" {:get (wrap-auth auth/checked)}]
  ["/auth/open" {:get auth/open}])

2. 路由组批量包装

将需要统一认证的路由归为一组,用reitit.ring/wrap-routes批量包装:

(require '[reitit.ring :as ring])

(defn api-routes [_opts]
  ["/auth"
   ["/login" {:post auth/login}]
   ["/open" {:get auth/open}]
   ; 批量包装需要认证的路由分支
   (ring/wrap-routes
    ["/checked" {:get auth/checked}]
    wrap-auth)])

3. 路由元数据指定中间件

在路由配置的:middleware字段中声明中间件,Reitit会自动应用:

(defn api-routes [_opts]
  ["/auth/login" {:post auth/login}]
  ["/auth/checked" {:get auth/checked
                    :middleware [wrap-auth]}]
  ["/auth/open" {:get auth/open}])

三、JWT Bearer认证的Kit极简示例

以下是完整的可运行示例:

1. 依赖配置(deps.edn)

{:deps {buddy/buddy-auth {:mvn/version "3.0.3"}
        buddy/buddy-sign {:mvn/version "3.4.1"}}}

2. 认证模块实现

(ns myapp.auth
  (:require [buddy.auth.backends.jws :as backends]
            [buddy.auth.middleware :as auth-middleware]
            [buddy.sign.jwt :as jwt]
            [ring.util.response :as resp]))

(def secret "topsecret")
(def jwt-backend (backends/jws {:secret secret
                                :token-name "Bearer"}))

(defn wrap-auth [handler]
  (-> handler
      (auth-middleware/wrap-authentication jwt-backend)
      (auth-middleware/wrap-authorization jwt-backend)))

; 生成JWT的登录接口
(defn login [req]
  (let [user (get-in req [:params :username])]
    (if user
      (resp/response {:token (jwt/sign {:username user :role :user} secret)})
      (resp/unauthorized "Missing username"))))

; 需认证的接口
(defn checked [req]
  (resp/response {:message "Authenticated"
                  :user (:identity req)}))

; 开放接口
(defn open [req]
  (resp/response {:message "Open access allowed"}))

3. 路由定义

(ns myapp.routes
  (:require [myapp.auth :as auth]
            [reitit.ring :as ring]))

(defn api-routes [_opts]
  ["/auth"
   ["/login" {:post auth/login}]
   ["/open" {:get auth/open}]
   ["/checked" {:get auth/checked
                :middleware [auth/wrap-auth]}]])

四、权限限制基础用法

如果需要角色级别的权限控制,可使用buddy.auth.accessrules实现:

1. 定义权限规则

(def access-rules
  [{:pattern #"^/admin"
    :handler (fn [req]
               (let [user (:identity req)]
                 (and user (= (:role user) :admin))))}
   {:pattern #"^/user"
    :handler (fn [req] (boolean (:identity req)))}])

2. 包装权限中间件

(defn wrap-access-control [handler]
  (accessrules/wrap-accessrules handler {:rules access-rules
                                         :on-error (fn [_req _err]
                                                     (resp/unauthorized "Forbidden"))}))

3. 应用到路由

(defn api-routes [_opts]
  ["/auth"
   ["/login" {:post auth/login}]
   ["/open" {:get auth/open}]
   (ring/wrap-routes
    ["/checked" {:get auth/checked}]
    auth/wrap-auth)
   ; 同时应用认证和权限控制
   (ring/wrap-routes
    ["/admin/panel" {:get admin/panel}]
    (comp auth/wrap-auth wrap-access-control))])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 09:02:07