First Touch of Travis CI
目前 Travis CI 给我的感觉和 Jekins 类似,每次 push 到 github 上, Travis 会自动跑一遍,比如按官方文档所说,对于 Java 项目,如果发现 pom.xml 文件,会使用 Maven 3 的一些 lifecycle。
对于一个 Java 项目,需要在 .git/ 目录下,新建文件 .travis.yml,最简
单的内容是:
1
| |
目前 Travis CI 给我的感觉和 Jekins 类似,每次 push 到 github 上, Travis 会自动跑一遍,比如按官方文档所说,对于 Java 项目,如果发现 pom.xml 文件,会使用 Maven 3 的一些 lifecycle。
对于一个 Java 项目,需要在 .git/ 目录下,新建文件 .travis.yml,最简
单的内容是:
1
| |
假设 CAS Server 的域名是 cas.server.com
CAS Server 的 webapp 是 spring web flow,登陆地址为:https://cas.server.com/cas/login
登出地址为:https://cas.server.com/cas/logout
语言参数为:locale=zh_CN,locale=en
除了配置 CAS Server 和 Client 外,需要配置环境,包括生成和导出导入证书,Tomcat配置SSL等。

原理:按照此图来说
用户访问CAS Client
其配置的 AuthenticationFilter 会拦截此请求,生成 service 参数,并重定向到 CAS Server 的登陆接口,url为 https://cas.server.com/login?service=redirect_url
用户在 CAS Server 输入 Credentials(一般就是用户名和密码)进行身份验证,成功后,CAS Server 会生成认证 cookie,即TGC。(另:TGC作为 cookie之外,也会换存在服务器本地,我猜测是不是服务器运行实例的内存中。)
CAS Server还会根据 service 参数,生成 Ticket,即ST。ST会保存在服务器,也会加在 url 后面,重定向回 client。url为 http://client_server_url:port/app_name?ticket=ST-*-*
Client 的 AuthenticationFilter 看到 ticket 参数后,会跳过,交由后面的 TicketValidationFilter 来处理。TicketValidationFilter 会利用 httpclient 工具访问 cas server 的 /serviceValidate 接口,将 ticket, service 传入该接口,验证 ticket 的有效性。
如果返回验证成功,就会把用户信息写入 client 的 session 里。
至此,SSO 会话就建立起来了。
结果就是:
用户在同一浏览器访问同一 client,不会去 CAS Server 认证,因为 AuthenticationFilter 会在 session 读取到用户信息。
用户在同一浏览器访问其他 client,AuthenticationFilter 在 session 里读不到用户信息,会去 cas login 接口认证,但是此时 cas login 接口会读取到存储在cas server域名下的 TGC,所以,CAS Server不会跳到登录页,只会根据 service 参数生成一个 ticket,传给 client。然后由TicketValidationFilter做一次交互验证。
cas server 一共定义了9个接口。client 会通过 url redirect 和 httpclient 的方式和 server 交互。
| 接口 | 说明 |
|---|---|
| /login | 认证接口 |
| /logout | 退出接口,销毁 TGC |
| /validate | 验证 ticket 接口,CAS1.0 |
| /serviceValidate | 同上,CAS2.0 |
| /proxy | 支持代理功能的接口 |
| /proxyValidate | 同上 |
| /CentralAuthenticationService | 用于和远程的 web services 交互 |
| /remoteLogin | 认证接口(新增) |
| /directLogin | 认证接口(新增) |
Credentials 用户提供的凭证,比如 用户名/密码,证书,IP地址,Cookie值等。
AuthenticationHandler 认证Handler,比如:AbstractUsernamePasswordAuthenticationHandler 负责处理 UsernamePasswordCredentials.
CredentialsToPrincipalResolvers 负责由 Credentials 生成 Principal 对象,每种 CredentialsToPrincipalResolvers 只处理 一种Credentials ,比如 UsernamePasswordCredentialsToPrincipalResolver 负责从 UsernamePasswordCredentials 中取出用户名,然后将其赋给生成的 SimplePrincipal 的 ID 属性。
AuthenticationMetaDataPopulators 负责将 Credentials 的一些属性赋值给 Authentication 的 attributes 属性。
Authentication Authentication是认证管理器的最终处理结果, Authentication 封装了 Principal ,认证时间,及其他一些属性(可能来自 Credentials)。
AuthenticationManager 认证管理器得到 Credentials 对象后,负责调度AuthenticationHandler 去完成认证工作,最后返回的结果是 Authentication 对象。
CentralAuthenticationService CAS 的服务类,对 Web 层提供了一些方法。该类还负责调用 AuthenticationManager 完成认证逻辑。
Compared to the former, it adds more features like “Spring Integration”.
Features like “Convention-based validation”, “GAE aware”.
1 2 3 4 5 6 | |
If the above command will fail because of missing archetypes in central repository, you can try to use staging repository like below
1
| |
CAS Client for Java 3.1/3.2 可以通过配置 web.xml 里的 context-params 和 filter init-params。每个 filter 都需要配置一系列的属性(properties)。filters 会查找这些属性:
如果在 filter 的 init-params 和 context 的参数中找到相同的值,则选用 init-params。
同样,filter 的顺序为:
! 如果使用 serverName 属性,请注意 fragment-URL(#后的 URL)不会发送给服务器。
一一介绍可用的 filters:
AuthenticationFilter 判断一个用户是否需要验证。如果需要,则重定向到 CAS server。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
Required Properties
Optional Properties:
有 renew, gateway, artifactParameterName, serviceParameterName。
猜测是支持 SAML 1.1 的 authentication filter。
1 2 3 4 5 6 7 8 9 10 11 12 | |
使用 SAML 1.1 协议验证 tickets。
1 2 3 4 5 6 7 8 9 10 11 12 | |
Required Properties
Optional Properties
Wraps an HttpServletRequest so that the getRemoteUser and getPrincipal return the CAS related entries.
包裹 HttpServletRequest,使 getRemoteUser 和 getPrincipal 返回 CAS 相关的入口。
1 2 3 4 | |
Required Properties
None
Optional Properties
None
Places the Assertion in a ThreadLocal for portions of the application that need access to it. This is useful when the Web application that this filter “fronts” needs to get the Principal name, but it has no access to the HttpServletRequest, hence making getRemoteUser() call impossible.
把这个 Assertion 放进 ThreadLocal 中,因为有些应用可能需要。比如:当 Web 应用需要拿到 Principal 的名字,但是它无法访问 HttpServletRequest,因此 getRemoteUser() 没有用。
! 没搞懂什么意思,猜测是 CAS Client 应用想要拿到登陆的用户名,但是用户名存储在 CAS Server 上。这个 filter 的作用就是把 Principal 放到 ThreadLocal 变量中。
1 2 3 4 | |
e.g. 一份稍完整的 CAS Client for Java 的 web.xml(未使用 SAML 1.1,为 CAS 协议)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | |
e.g. 使用 SAML 1.1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | |
! SingleSignOutFilter 会影响到 character encoding。建议显式地配置下 VT Character Encoding Filter 或 Spring Character Encoding Filter。
CAS 对 Single Sign Out support 的支持,涉及到对一个 filter 和一个 ContextListener 的配置。需要注意的一点是,如果以 Web filters 的形式为 Java 配置 CAS Client,登出的 filter 需要在其他 filters 前面。
PS: Order of Required Filters 全文链接 Order of Required Filters
How to configure the filters is described on the pages above. This section details the order in which the filters should appear:
1 2 3 | |
Create the Certificate
打开终端,进到 home 目录,运行命令:
1
| |
需要输入:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
如何给这些值?
For the keystore password you should enter “changeit” without the quotation marks. When prompted for the first and last name, you should enter your machine name during development. The rest of the data does not matter. Then obviously answer “yes” to the question of whether it’s correct.
注意: CAS 协议需要走 HTTPS,为了保证能够工作, “first and last name” 为 $FULL_MACHINE_NAME。Mac 上获取计算机全名的方法是:
scutil --get ComputerName或者scutil --get LocalHostName。
下一步,打开 $TOMCAT_HOME/conf/server.xml,找到这一块,去掉注释即可:
1 2 3 4 5 | |
重启 Tomcat,访问
1
| |
Any application that wishes to securely connect to this Tomcat instance would need to import the certificate. You can export the certificate that’s compatible with other JVM keystores by executing the following command:
所有想访问该 Tomcat 实例的应用都需要导入证书。首先导出证书,需要输入 keystore 的密码,这里就是 changeit:
1
| |
输出是:
1 2 | |
You can then import the server.crt into other JVM keystore’s by executing a command similar to this:
1
| |
It’s recommended that you add it to the JVM keystore of your local development machine to facilitate testing.
Maven War Overlay1
非常简单,mvn package 生成的 war 包,直接扔进 Tomcat 安装目录下的 webApps 目录。然后重启下 Tomcat。
不需要任何额外的配置,默认是 localhost:8080/war_name/
列表处理
Lisp 列表
1 2 3 4 | |
Lisp 原子
() 空列表
空列表既是原子,也是列表
原子和列表都叫做 符号表达式(symbolic expression),简称 s-expression。
You have typed C-h, the help character. Type a Help option: (Use SPC or DEL to scroll through this text. Type q to exit the Help command.)
常用的是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | |
从网上找到的一个简易的方法,easy to be understood:
1 2 3 4 5 6 | |
1 2 3 | |
光标上用点颜色,看起来舒服点。红色是退回Emacs(使用C-z,再按一次C-z回到evil),
1 2 3 | |
这里有个terminology的区别:vim中的mode指的是Normal, Insert, Visual等,vim是模式编辑器。但是在Emacs中,mode是指对特定文本定义的一组快捷键。所以,evil把vim中的mode称作state。
通过一堆variable设置evil,可以通过 M-x customize-group RET evil RET 查看当前的设置。
setq设置全局变量,setq-default设置buffer-local的变量,而且要在evil加载前修改1。
1 2 3 | |
下面列出的variable,基本上默认值和vim的行为类似,但是evil-want-C-u-scroll默认不是t。
evil-auto-indent [Variable]
t(default), nil,类似vim中的autoindent。
evil-shift-width [Variable]
The number of columns a line is shifted by the commands > and <.
evil-repeat-move-cursor [Variable]
如果t(default),使用
.重复时光标改变位置。
evil-find-skip-newlines [Variable]
如果t,那么f,F,t,T会查找到其他行。nil(default)。
evil-move-cursor-back [Variable]
t(default),和vim的行为类似,退出insert state时,光标前移一格。
evil-want-fine-undo [Variable]
If t, then a change-based action like cw may be undone in several steps. If nil (the default), then it is undone in one step.
evil-regexp-search [Variable]
t(default),
/,?使用正则表达式
evil-search-wrap [Variable]
t(default),
/,?搜索是到底后从头再搜索。
evil-flash-delay [Variable]
The number of seconds to flash search matches when pressing n and N.
evil-want-C-i-jump [Variable]
If t (the default), then C-i jumps forwards in the jump list. If nil, then C-i inserts a tab.
evil-want-C-u-scroll [Variable]
If t, then C-u scrolls the buffer. If nil (the default), then C-u begins a numeric prefix argument.
这个之前也已经涉及过,现在全面了解下:
1 2 3 | |
一共这么多:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
默认是进入 Normal State。我也就不修改了。
Evil 的键映射存储在多个keymaps中,每个 state 有一个全局的 keymap,比如对应于Normal State 的evil-normal-state-map。
通过 Emacs 的 define-key 来修改。
1 2 | |
evil-maps.el 包含所有的键绑定。
1 2 3 4 5 6 7 8 9 10 11 12 | |
每个 state 还有一个 buffer-local 的 keymap。也就是特定于该 buffer,优先于 global keymap。这些可以通过 mode hook 修改。
1 2 3 4 5 6 7 8 9 10 11 12 | |
Evil 提供的方法,可以往 Emacs 的 keymap 中添加特定 state 的键绑定。比如:
定义了一个 minor mode,叫做 foo-mode。然后往该 mode 的 normal state 下修改键绑定。
1 2 3 4 5 | |
然后用 hook,添加到 text-mode-hook 里。
1
| |
什么是 vim 的 magic?
主要涉及到正则表达式。先留几个参考资料:
To Be Continued
Strictly speaking, the order only matters if the variable affects the way Evil is loaded. This is the case with some of the ‘evil-want-’ variables.↩
使用vagrant搭建Linux虚拟机
1 首先安装 virtualbox
2 安装vagrant
3 打开cmd,或者终端,运行以下命令,注意这一步会下载一个Linux发行版,大约3,400M吧。所以,你也可以用迅雷到网上下载下来,然后把 http://files.vagrantup.com/precise32.box 改成你文件的路径,比如我的是file:///Users/pieux/Documents/o/precise32.box
1 2 | |
4 SSH 进入linux吧!vagrant ssh,退出就是 exit
5 关闭Linux的命令是,休眠vagrant suspend,或者关闭vagrant halt。
1 2 3 4 5 6 7 8 9 | |
1 2 3 4 5 | |
编辑命令
1 2 3 4 5 6 7 8 9 10 | |
重新执行命令
1 2 3 4 | |
控制命令
1 2 3 4 5 | |
1 2 3 4 5 | |
简单的正则表达式:
1 2 3 4 5 6 7 8 | |
1 2 3 4 5 | |
1 2 3 4 5 6 7 8 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
1 2 3 4 | |