Skip to content

Instantly share code, notes, and snippets.

@matstani
Last active Dec 14, 2015
Embed
What would you like to do?
Compojure、Friendを使って、フォーム認証を行うコード。
(ns helloworld.handler
(:require [ring.util.response :as response]
[compojure.core :refer :all]
[compojure.handler :as handler]
[compojure.route :as route]
[hiccup.page :refer [html5]]
[hiccup.element :refer [link-to]]
[hiccup.form :as form]
[cemerick.friend :as friend]
(cemerick.friend [workflows :as workflows]
[credentials :as creds])))
;; 仮のアカウント定義
(def users {"admin" {:username "admin"
:password (creds/hash-bcrypt "adminpassword")
:roles #{::admin}}
"user" {:username "user"
:password (creds/hash-bcrypt "userpassword")
:roles #{::user}}})
;; ::admin ロールは ::user ロールを兼ねる
(derive ::admin ::user)
;; ページレイアウト
(defn layout [& content]
(html5
[:head [:title "auth and authz using friend."]]
[:body
content]))
;; 認証が必要なページの定義
(defroutes secure-routes
;; /admin以下は ::admin ロールが必要
(context "/admin" request
(friend/wrap-authorize
(routes
(GET "/page1" [] (layout "admin page1."))
(GET "/page2" [] (layout "admin page2.")))
#{::admin}))
;; /user以下は ::user ロールが必要
(context "/user" request
(friend/wrap-authorize
(GET "/private" [] (layout "private page."))
#{::user})))
;; indexページ
(def index
(layout
[:div
[:ul
[:li (link-to "/admin/page1" "Admin page1")]
[:li (link-to "/admin/page2" "Admin page2")]
[:li (link-to "/user/private" "User's private page.")]]]
[:div (link-to "/login" "Login")]
[:div (link-to "/logout" "Logout")]))
(def index-handler
(GET "/" [] index))
;; ログインフォーム
(def login-form
(layout
(form/form-to [:post "/login"]
[:div
[:div
(form/label "username" "user name:")
(form/text-field "username")]
[:div (form/label "password" "password:")
(form/password-field "password")]
[:div (form/submit-button "login!")]])))
(def login-handler
(GET "/login" [] login-form))
(defroutes app-routes
index-handler
login-handler
secure-routes
;;ログアウトページ
(friend/logout (ANY "/logout" request (response/redirect "/")))
(route/not-found "Not Found"))
(def app
(-> app-routes
;;認証用ミドルウェア(依存ミドルウェアの内側に置く)
(friend/authenticate {:credential-fn (partial creds/bcrypt-credential-fn users)
:workflows [(workflows/interactive-form)]})
handler/site))
(defproject helloworld "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:dependencies [[org.clojure/clojure "1.4.0"]
[compojure "1.1.5"]
[com.cemerick/friend "0.1.3"]
[hiccup "1.0.2"]]
:plugins [[lein-ring "0.8.2"]]
:ring {:handler helloworld.handler/app}
:profiles
{:dev {:dependencies [[ring-mock "0.1.3"]]}})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment