β

只是Flask-CAS的Demo而已

昔我往矣 261 阅读
 

起了个轻松一点的标题,但其实是折腾CAS的心酸史,跨越大半年的时间,终于搞定了Flask-CAS这个模块。这是个悲伤的故事!

从头说起,CAS是central authentication service的缩写,也是一套单点登录协议标准。每个公司内部有很多自研的、商业的或者开源的系统,如果有了CAS,你只需要在某个接入CAS的站点登录,其它站点就可以自动登录了,不需要再单独验证。听起来很爽吧。这里不讲解具体原理,因为通过搜索引擎找到这篇文章的人应该都是和我曾经一样走投无路只想解决问题的人。。。

没错,我们公司里就部署了这么一套cas系统,我们采用了开源的企业级解决方案 https://www.apereo.org/projects/cas , 后台采用OpenLDAP做认证,公司大多数系统都愉快的接入了这套cas。

大半年前,我用Flask写了一套web管理系统想接入公司的CAS做认证,使用 Flask-CAS ,不成功,太忙就放弃了,转而走上了 HTTP Basic access authentication + LDAP 的邪路。最近又遇到这么个问题,一个要修改状态的服务,为了防止用户伪造身份,所以还是想接入cas做下身份校验。走上了和Flask-CAS死磕的道路。

首先,不知为何,pip只能安装Flask-CAS的1.0.0版本,不信你看 https://pypi.python.org/simple/flask-cas/ ,但是为啥我又看到了1.0.1的版本,不信你看 https://pypi.python.org/pypi/Flask-CAS 。我也没太放在心上,反正先搭建起来再看呗。

构建环境

$ virtualenv demo
$ cd demo
$ source bin/activate
$ pip install Flask-CAS

然后demo.py代码如下:

from flask import Flask
from flask_cas import CAS, login_required
from flask.ext.cas import login
from flask.ext.cas import logout

app = Flask(__name__)
cas = CAS(app)

app.config['CAS_SERVER'] = 'https://cas.xnow.me'
app.config['CAS_AFTER_LOGIN'] = 'test'
app.config['SECRET_KEY'] = 'guess'
    
@app.route("/")
@login_required
def index():
    username = cas.username
    return "index of" + username

@app.route("/test")
@login_required
def test():
    username = cas.username
    return "test page of " + username

app.run(host='0.0.0.0', port=5002, debug=True)

解决问题

跑起来就遇到了第一个错误

xml.parsers.expat.ExpatError
ExpatError: not well-formed (invalid token): line 16, column 120

反正Flask-CAS源代码也就两个文件,于是在源代码里面各种加调试,居然找到门路,是在检查valiate的时候,CAS返回的数据居然是cas登录页面的html源码,于是去看文档, Flask-CAS 有可疑配置参数是 CAS_VALIDATE_ROUTE ,默认值: /cas/serviceValidate ,同事说我们cas也有 /validate路径的,于是我加了一行配置:

app.config['CAS_VALIDATE_ROUTE'] = '/validate'

还是一样的报错,这个路径返回要么是yes,要么是no。但是看样子cas客户端想要的是一个xml。无意间看到CAS的 文档 ,发现CAS除了/validate,还有 /serviceValidate /proxyValidate ,瞎猫碰上死耗子,接着改配置:

app.config['CAS_VALIDATE_ROUTE'] = '/serviceValidate'

然后惊喜的发现,真的返回了xml,而且连报错都换了样子:

KeyError
KeyError: 'cas:attributes'

于是接着往下读源码,返回的数据里确实没有 cas:attributes 属性,走投无路,去问Google,发现有close的issue,大喜,然后也发现 Flask-CAS 在Github上最近的一次更新已经修复了 cas:attributes 的问题,就在1.0.1的版本里。

$ git clone git@github.com:cameronbwhite/Flask-CAS.git
$ cd Flask-CAS
$ python setup.py install

然后就装上去了,然后再运行,就这么返回了正确结果。幸福来的太快了~谁来告诉我,为啥pip装不了1.0.1版本呢?

Demo源码

from flask import Flask
from flask_cas import CAS, login_required
from flask.ext.cas import login
from flask.ext.cas import logout
import logging

app = Flask(__name__)
cas = CAS(app)

app.config['CAS_SERVER'] = 'https://cas.xnow.me'
app.config['CAS_AFTER_LOGIN'] = 'test'
app.config['SECRET_KEY'] = '123'
app.config['CAS_VALIDATE_ROUTE'] = '/serviceValidate'

    
@app.route("/")
@login_required
def index():
    username = cas.username
    return "index" + username

@app.route("/test")
@login_required
def test():
    username = cas.username
    return "test page" + username

app.run(host='0.0.0.0', port=5002, debug=True)
 
作者:昔我往矣
原文地址:只是Flask-CAS的Demo而已, 感谢原作者分享。

发表评论