Authentication

122 views
Skip to first unread message

Slobodan Milnović

unread,
Jan 18, 2012, 1:42:15 PM1/18/12
to restas
Hi,

I'm using restas from the latest quicklisp repository, and sbcl
1.0.55.

I have tried to combine the simple example from "hello world" tutorial
with HTTP authentication in the decorators part of the manual.

This is what it looks like:


(restas:define-module :restas-example-1
(:use :cl :cl-who))

(in-package :restas-example-1)

(restas:define-route main ("" :method :get)
(cl-who:with-html-output-to-string (out)
(:html
(:body
((:form :method :post )
((:input :name "message"))
((:input :type "submit" :value "Send")))))))

(restas:define-route main/post ("" :method :post)
(cl-who:with-html-output-to-string (out)
(:html
(:body
(:div
(:b (cl-who:fmt "test message: ~A" (hunchentoot:post-parameter
"message"))))
((:a :href (restas:genurl 'main)) "Try again")))))

(defclass moja-auth-ruta (routes:proxy-route) ())

(defmethod routes:route-check-conditions ((route moja-auth-ruta)
bindings)
(and (call-next-method)
(multiple-value-bind (user password)
(hunchentoot:authorization )
(or (and (string= user "pero")
(string= password "peric"))
(hunchentoot:require-authorization )))))

(defun @http-auth-potrebno (route)
(make-instance 'moja-auth-ruta :target route))

(restas:mount-submodule cjovotmp (#:restas-example-1 @http-auth-
potrebno))

When I try to start it with

RESTAS-EXAMPLE-1> (restas:start '#:restas-example-1 :port 8080)

instead of standard response slime freezes, and when i try to go to
localhost:8080, I get response from the hunchentoot saying there is no
"/":

Not Found

The requested URL / was not found on this server.
Hunchentoot 1.2.2 (SBCL 1.0.55) at localhost:8080


Without the auth part from decorators, the hello world example works
fine. I guess I have misunderstood the way the authorization can be
done in restas.

Actually, what I would like to do is to have an redirect, if the
session is not authorized, to route to some "auth" page, on which I
would use my own authorization method instead, but since I'm stuck
with this, I would like to ask for help.

Andrey Moskvitin

unread,
Jan 19, 2012, 6:42:59 AM1/19/12
to res...@googlegroups.com
Hi,

I do not see a problem. You could not give full code with this problem?

Andrey

2012/1/18 Slobodan Milnović <slobodan...@gmail.com>:

Slobodan Milnović

unread,
Jan 19, 2012, 6:50:05 AM1/19/12
to res...@googlegroups.com
Hi,

This is the full code. :)

I've tried several times to kill sbcl, restart slime, load restas,
hunchentoot and cl-who with quicklisp, and everything is ok until I do
restas:start. After that, sbcl freezes, and hunchentoot reports error.
If I comment out the auth code, then the "hello world" part works fine
using restas:start

2012/1/19 Andrey Moskvitin <arch...@gmail.com>:

Andrey Moskvitin

unread,
Jan 19, 2012, 7:14:18 AM1/19/12
to res...@googlegroups.com
Oh, you mount module into itself :(  This leads to infinite recursion.

I suggest the following code:

(asdf:operate 'asdf:load-op '#:restas)

(defpackage #:http-auth
(:use #:cl)
(:export moja-auth-ruta))

(in-package #:http-auth)

(defclass moja-auth-ruta (routes:proxy-route) ())

(defmethod routes:route-check-conditions ((route moja-auth-ruta)
bindings)
(and (call-next-method)
(multiple-value-bind (user password)
(hunchentoot:authorization )
(or (and (string= user "pero")
(string= password "peric"))
(hunchentoot:require-authorization )))))

(defun @http-auth-potrebno (route)
(make-instance 'moja-auth-ruta :target route))

(restas:define-module #:restas.hello-world
(:use :cl)
(:decorators '@http-auth-potrebno))

(in-package #:restas.hello-world)

(restas:define-route main ("")
"<h1>Hello world!</h1>")


(restas:start '#:restas.hello-world :port 8080)

Andrey

2012/1/19 Slobodan Milnović <slobodan...@gmail.com>:

Slobodan Milnović

unread,
Jan 19, 2012, 7:28:19 AM1/19/12
to res...@googlegroups.com
I see.

Thanks, I'll try it tonight. :)

Slobodan Milnović

unread,
Jan 25, 2012, 12:44:41 PM1/25/12
to res...@googlegroups.com
Hi, I have tried this code, but the chromium reports that there are
too many redirects
"310 (net::ERR_TOO_MANY_REDIRECTS), but I'm not sure where exactly.

(defpackage #:http-auth
(:use #:cl)

(:export #:moja-auth-ruta
#:*auth-korisnik*))

(in-package #:http-auth)

(defclass korisnik ()
((ime :accessor korisnik-ime :initarg :ime :initform nil)
(loza :accessor korisnik-loza :initarg :loza :initform nil))
(:documentation "klasa za korisnika"))

(defvar *auth-korisnik* (make-instance 'korisnik))

(defclass moja-auth-ruta (routes:proxy-route) ())

(defmethod routes:route-check-conditions ((route moja-auth-ruta) bindings)
(and (call-next-method)

(or (korisnik-ime *auth-korisnik*)
(restas:redirect 'admin))))

(defun @http-auth-potrebno (route)
(make-instance 'moja-auth-ruta :target route))

(restas:define-module #:restas.hello-world
(:use :cl)
(:decorators '@http-auth-potrebno))

(in-package #:restas.hello-world)

(restas:define-route admin ("" :method :get)


(cl-who:with-html-output-to-string (out)
(:html
(:body
((:form :method :post)

((:input :name "korisnik"))
((:input :name "lozinka" :type "password"))
((:input :type "submit" :value "Ulogiraj se")))))))

(restas:define-route admin/post ("" :method :post)
(or (http-auth::korisnik-ime http-auth:*auth-korisnik*)
(if
(and (string= (hunchentoot:post-parameter "korisnik") "pero")
(string= (hunchentoot:post-parameter "lozinka") "peric"))
(progn
(setf (http-auth::korisnik-ime http-auth:*auth-korisnik*)
(hunchentoot:post-parameter "korisnik"))
(setf (http-auth::korisnik-loza http-auth:*auth-korisnik*)
(hunchentoot:post-parameter "lozinka")))))
(restas:redirect 'main))

Andrey Moskvitin

unread,
Jan 25, 2012, 3:16:34 PM1/25/12
to res...@googlegroups.com
Hi,

Replace

> (defmethod routes:route-check-conditions ((route moja-auth-ruta) bindings)
>  (and (call-next-method)
>       (or (korisnik-ime *auth-korisnik*)
>           (restas:redirect 'admin))))

on

(defmethod routes:route-check-conditions ((route moja-auth-ruta) bindings)
(and (call-next-method)
(or (korisnik-ime *auth-korisnik*)

(eql (restas:route-symbol (routes:proxy-route-target route))
'restas.hello-world:admin)
(restas:redirect 'restas.hello-world:admin))))

And change 'ADMIN route URL:

(restas:define-route admin ("admin" :method :get)


2012/1/25 Slobodan Milnović <slobodan...@gmail.com>:

Slobodan Milnović

unread,
Feb 6, 2012, 1:32:36 PM2/6/12
to res...@googlegroups.com
Dear Andrey,

I am sorry, but I don't understand how I can use auth in this way. I have tried your change, but I still get only admin page, and regardless of the correct username/password, I still get redirected back to it. I have tried modifying it in various ways, but with no success... 

Also, what is annoying is that I cannot load it straightfoward because of interdependences between various packages, but I have to eval each statement/function manually.

Perhaps it works for you after you change something and are still inside your lisp session, but I'm wondering if it works for you if you start it from the blank image?

I'm checking out your simple-auth package too, but it seems to me that it doesn't use any decorators, but is using completely different technique, requirements. I don't like that because it seems to me that I'd have to use :requirements for each route I make manually.

Slobodan Milnović

unread,
Feb 12, 2012, 1:42:22 PM2/12/12
to res...@googlegroups.com
Dear Andrey,

I appologize for spamming, but I have found the mistake. If there is a
better way, it would be great to know it, but as far as I can see it,
this works. I have used paste.lisp.org, so that I don't clutter here -
http://paste.lisp.org/display/127720

Main changes are "provjera-lozinke" function which checks if the user
has logged in properly, and I also changed route-check-conditions. It
seems that whenever I enter username/password into the "admin" route,
then restas searches for the :post route, and that is the reason why I
was stuck into repeated reload of admin :get route. So
route-check-conditions checks if the password is ok, if the
route-symbol requested is :post route and after that the :get route.


(defmethod routes:route-check-conditions ((route moja-auth-ruta) bindings)
(and (call-next-method)
(or

(provjera-lozinke)


(eql (restas:route-symbol (routes:proxy-route-target route))

'restas.hello-world:admin/post)


(eql (restas:route-symbol (routes:proxy-route-target route))
'restas.hello-world:admin)
(restas:redirect 'restas.hello-world:admin))))

And in the admin :post route I have an check if the username/password is ok

(restas:define-route admin/post ("admin" :method :post)
(if (http-auth::provjera-lozinke)
(restas:redirect 'main)
(restas:redirect 'admin)))


I don't know if there can be a more elegant solution (I'm sure there
can be), but I hope this will help anyone trying restas.

Of course, there also should be a better way to arrange http-auth and
restas.hello-world, because as it is now, you cannot just load it, but
you have to mannually eval each defun/expression, and not in the order
it is in the file. I think I know how to do it according to the restas
documentation and examples. Well, it works as it is. :-D

I am wondering how does restas handle concurent sessions, from
different users and from the same user? Is there any handling of it
whatsoever, is there an separate hunchentoot thread (as I think
weblocks does it), or do I have to make an dispatch list by myself
(with for example a list of logged in users and similar stuff)?

Andrey Moskvitin

unread,
Feb 14, 2012, 10:51:40 AM2/14/12
to res...@googlegroups.com
Hi Slobodan,

I'm sorry, but I'm very busy lately and while I can not help you: (

Andrey

2012/2/12 Slobodan Milnović <slobodan...@gmail.com>:

Slobodan Milnović

unread,
Feb 14, 2012, 4:51:33 PM2/14/12
to res...@googlegroups.com
Hi Andrey,

It is not a problem. I have managed to solve my problem, now my simple
app works, thank you. :-) There should be a few tweaks, but it is ok.

I'll study all of the examples, and I have been checking all of the
apps and libs that you have been working on on the github, that are
using restas, so to try to understand how I can use restas in more
advanced ways that I'm doing now.

Reply all
Reply to author
Forward
0 new messages