Attachment 'cas.py'

Download

   1 # -*- coding: iso-8859-1 -*-
   2 """
   3     MoinMoin - CAS authentication
   4 
   5     Jasig CAS authentication module
   6 
   7     @copyright: 2009 MoinMoin:RichardLiao
   8     @license: GNU GPL, see COPYING for details.
   9 """
  10 import urlparse
  11 import urllib, urllib2
  12 import time, re
  13 
  14 from MoinMoin import log
  15 logging = log.getLogger(__name__)
  16 
  17 from MoinMoin.auth import BaseAuth
  18 from MoinMoin import user, wikiutil
  19 
  20 
  21 class PyCAS(object):
  22     """A class for working with a CAS server."""
  23     
  24     def __init__(self, url, renew=False, **kwords):
  25         self.url = url
  26         self.renew = renew
  27         self.paths = {
  28             'login_path': '/login',
  29             'logout_path': '/login',
  30             'validate_path': '/validate',
  31         }
  32         self.paths.update(kwords)        
  33     
  34     def login_url(self, service):
  35         """Return the login URL for the given service."""
  36         base = self.url + self.paths['login_path'] + '?service=' + urllib.quote_plus(service)
  37         if self.renew:
  38             base += "&renew=true"
  39         return base
  40 
  41     def logout_url(self, url=None):
  42         """Return the logout URL."""
  43         base = self.url + self.paths['logout_path'] 
  44         if url:
  45             base += '?url=' + urllib.quote_plus(url)
  46         return base
  47 
  48     def validate_url(self, service, ticket):
  49         """Return the validation URL for the given service. (For CAS 1.0)"""
  50         base = self.url + self.paths['validate_path'] + '?service=' + urllib.quote_plus(service) + '&ticket=' + urllib.quote_plus(ticket)
  51         if self.renew:
  52             base += "&renew=true"
  53         return base
  54 
  55     def validate_ticket(self, service, ticket):
  56         """Validate the given ticket against the given service."""
  57         f = urllib2.urlopen(self.validate_url(service, ticket))
  58         valid = f.readline()
  59         valid = valid.strip() == 'yes'
  60         user = f.readline().strip()
  61         
  62         return (valid, user)
  63         
  64 class CASAuth(BaseAuth):
  65     """ handle login from CAS """
  66     name = 'CAS'
  67     logout_possible = True
  68 
  69     def __init__(self, auth_server, login_path = "/login", logout_path = "/logout", validate_path = "/validate"):
  70         BaseAuth.__init__(self)
  71         self.auth_server = auth_server
  72         self.login_path = login_path
  73         self.logout_path = logout_path
  74         self.validate_path = validate_path
  75 
  76     def request(self, request, user_obj, **kw):
  77         ticket = request.args.get('ticket')
  78         action = request.args.get("action", [])
  79         logoutRequest = request.args.get('logoutRequest', [])
  80         url = request.getBaseURL() + urllib.quote_plus(request.getPathinfo().encode('utf-8'))
  81         
  82         # # handle logout request from CAS
  83         # if logoutRequest:
  84             # logoutRequestMatch = re.search("<samlp:SessionIndex>(.*)</samlp:SessionIndex>", logoutRequest[0])
  85             # service_ticket = logoutRequestMatch.group(1)
  86             # if service_ticket:
  87                 # # TODO: logout
  88                 # return self.logout(request, user_obj)
  89         
  90         # authenticated user
  91         if user_obj and user_obj.valid:
  92             return user_obj, True
  93         
  94         # anonymous
  95         if not ticket and not "login" in action:
  96             return user_obj, True
  97             
  98         # valid ticket on CAS
  99         if ticket:
 100             valid, username = self.cas.validate_ticket(url, ticket[0])
 101             if valid:
 102                 u = user.User(request, auth_username=username, auth_method=self.name)
 103                 u.valid = valid
 104                 # auto create user
 105                 u.create_or_update(True)
 106                 return u, True
 107                 
 108         # login
 109         request.http_redirect(self.cas.login_url(url))
 110         
 111         return user_obj, True
 112                 
 113     def logout(self, request, user_obj, **kw):
 114         if self.name and user_obj and user_obj.auth_method == self.name:
 115             url = request.getBaseURL() + urllib.quote_plus(request.getPathinfo().encode('utf-8'))
 116             request.http_redirect(self.cas.logout_url(url))
 117         
 118             user_obj.valid = False
 119             
 120         return user_obj, True
 121     
 122     def _cas(self):
 123         paths = {
 124             'login_path': self.login_path,
 125             'logout_path': self.logout_path,
 126             'validate_path': self.validate_path,
 127         }
 128         
 129         return PyCAS(self.auth_server, **paths)
 130     cas = property(_cas)
 131     

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2009-09-01 08:59:40, 3.2 KB) [[attachment:cas.pep8.patch]]
  • [get | view] (2009-09-01 06:58:47, 4.3 KB) [[attachment:cas.py]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.