2013-07-04 70 views
2

我正在構建一個簡單的練習Web應用程序,與朋友一起登錄,並試圖從教程示例dummy內存數據庫轉換到訪問我的DynamoDB數據庫。Friend的bcrypt-credential-fn的正確用法是什麼?

(handler/site 
(friend/authenticate app{ 
        :login-uri "/login" 
        :unauthorized-redirect-uri "/login" 
        :credential-fn (partial creds/bcrypt-credential-fn users) 
        :workflows [(workflows/interactive-form)]}))) 

(defn users 
[uname] 
(read-string (get-in (db/valid-user? uname "UB") [:item :friend-map]))) 

的問題,我的用戶的功能,我的理解出現(這可能很可能是在那裏我錯了)閱讀朋友的源代碼是bcrypt的憑據-FN帶參數調用一個函數從/ login提供的用戶名。我見過的示例/教程似乎遵循這種模式。

如果我把用戶喜歡,「[email protected]」一個用戶名,它返回一個哈希地圖朋友憑據

{"[email protected]" {:username "[email protected]", 
       :password "$2a$10$rtDxqCqZRIRFFzjCYD9d.uiQ2NuUMXto.jCbWNPtVKF1y/d4WPL/C",   
       :roles #{:practice.models.db/admin}}} 

如果我硬編碼用戶名到用戶的功能,工作正常,我可以用它登錄,但用uname或(str uname)替換時,只是爲了確保它是一個字符串。我得到一個空指針異常

java.lang.NullPointerException 
BCrypt.java:663 org.mindrot.jbcrypt.BCrypt.hashpw 
BCrypt.java:763 org.mindrot.jbcrypt.BCrypt.checkpw 
credentials.clj:18 cemerick.friend.credentials/bcrypt-verify 
credentials.clj:47 cemerick.friend.credentials/bcrypt-credential-fn 
AFn.java:163 clojure.lang.AFn.applyToHelper 
AFn.java:151 clojure.lang.AFn.applyTo 
core.clj:619 clojure.core/apply 
core.clj:2396 clojure.core/partial[fn] 
RestFn.java:408 clojure.lang.RestFn.invoke 
workflows.clj:80 cemerick.friend.workflows/interactive-form[fn] 
friend.clj:180 cemerick.friend/authenticate*[fn] 
core.clj:2485 clojure.core/map[fn] 
LazySeq.java:42 clojure.lang.LazySeq.sval 
LazySeq.java:60 clojure.lang.LazySeq.seq 
RT.java:484 clojure.lang.RT.seq 
core.clj:133 clojure.core/seq 
core.clj:2523 clojure.core/filter[fn] 
LazySeq.java:42 clojure.lang.LazySeq.sval 
LazySeq.java:60 clojure.lang.LazySeq.seq 
LazySeq.java:82 clojure.lang.LazySeq.first 
RT.java:577 clojure.lang.RT.first 
core.clj:55 clojure.core/first 
friend.clj:180 cemerick.friend/authenticate* 
friend.clj:208 cemerick.friend/authenticate[fn] 
keyword_params.clj:32 ring.middleware.keyword-params/wrap-keyword-params[fn] 
nested_params.clj:70 ring.middleware.nested-params/wrap-nested-params[fn] 
params.clj:58 ring.middleware.params/wrap-params[fn] 
multipart_params.clj:106 ring.middleware.multipart-params/wrap-multipart-params[fn] 
flash.clj:31 ring.middleware.flash/wrap-flash[fn] 
session.clj:85 ring.middleware.session/wrap-session[fn] 
resource.clj:24 ring.middleware.resource/wrap-resource[fn] 
file_info.clj:63 ring.middleware.file-info/wrap-file-info[fn] 
middleware.clj:12 hiccup.middleware/wrap-base-url[fn] 
Var.java:415 clojure.lang.Var.invoke 
reload.clj:18 ring.middleware.reload/wrap-reload[fn] 
stacktrace.clj:15 ring.middleware.stacktrace/wrap-stacktrace-log[fn] 
stacktrace.clj:79 ring.middleware.stacktrace/wrap-stacktrace-web[fn] 
jetty.clj:18 ring.adapter.jetty/proxy-handler[fn] 
(Unknown Source)           
ring.adapter.jetty.proxy$org.eclipse.jetty.server.handler.AbstractHandler$0.handle 
HandlerWrapper.java:111 org.eclipse.jetty.server.handler.HandlerWrapper.handle 
Server.java:349 org.eclipse.jetty.server.Server.handle 
AbstractHttpConnection.java:452 org.eclipse.jetty.server.AbstractHttpConnection.handleRequest 
AbstractHttpConnection.java:894 org.eclipse.jetty.server.AbstractHttpConnection.content 
AbstractHttpConnection.java:948  
org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content 
HttpParser.java:857 org.eclipse.jetty.http.HttpParser.parseNext 
HttpParser.java:235 org.eclipse.jetty.http.HttpParser.parseAvailable 
AsyncHttpConnection.java:76 org.eclipse.jetty.server.AsyncHttpConnection.handle 
SelectChannelEndPoint.java:609 org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle 
SelectChannelEndPoint.java:45 org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run 
QueuedThreadPool.java:599 org.eclipse.jetty.util.thread.QueuedThreadPool.runJob 
QueuedThreadPool.java:534 org.eclipse.jetty.util.thread.QueuedThreadPool$3.run 
Thread.java:722 java.lang.Thread.run 

我在做什麼錯在這裏?

回答

3

所以我想通了。

我的錯誤是將示例數據過於字面。

bcrypt-credntials-fn正在尋找:從它調用的函數返回的哈希映射中的用戶名,這意味着我的憑據映射嵌套得太深了。這在我的例子中有效。

{:username "[email protected]", 
      :password "$2a$10$rtDxqCqZRIRFFzjCYD9d.uiQ2NuUMXto.jCbWNPtVKF1y/d4WPL/C",   
      :roles #{:practice.models.db/admin}} 

它會努力工作,編碼,因爲它會尋找基本[「[email protected]」:用戶名],這是有效的。

希望這可以幫助任何人有同樣的問題。

+0

我犯的同樣錯誤的假設和我通過閱讀你的問題解決了我的問題,回答。非常感謝您的問候! – bzg

+0

很高興我能幫忙:) – VFe

0
(def page (handler/site 
      (friend/authenticate 
       routes 
       {:allow-anon? true 
       :login-uri "/login" 
       :default-landing-uri "/" 
       :unauthorized-handler #(-> (h/html5 
              misc/head 
              (misc/body [:h3 "You do not have sufficient privileges to access " (:uri %)] 
                [:a {:class "button secondary" :href "/interactive_form"} "Main"])) 
             resp/response 
             (resp/status 401)) 
       ;:credential-fn #(creds/bcrypt-credential-fn @users %) 
       :credential-fn #(creds/bcrypt-credential-fn db/get-user %) 
       :workflows [(workflows/interactive-form)]}))) 

...

(ns myapp.models.db 
    (:require [clojure.java.jdbc :as sql]) 
    (:import java.sql.DriverManager)) 

(def db {:classname "org.sqlite.JDBC", 
     :subprotocol "sqlite", 
     :subname "db.sq1"}) 

(defn create-user-table [] 
    (sql/with-connection 
    db 
     (sql/create-table 
     :userstable 
     [:username "varchar(20) PRIMARY KEY"] 
     [:password "varchar(100)"] 
     [:email "varchar(100)"] 
     [:balance "float"] 
     [:roles "boolean"]))) 

(defn add-user-record [user] 
    (if-not (.exists (java.io.File. "./db.sq1")) 
    (create-user-table)) 

    (sql/with-connection db 
    (sql/insert-record :userstable user))) 

(defn get-user [name] 
    (sql/with-connection db 
    (sql/with-query-results 
     res ["select * from userstable where username = ?" name] (first res)))) 

... 也讓users.clj的用戶,因爲它是