CAS对接的坑,一个字母引发的惨案

有两个类定义如下

管理后台生产的JSON配置是 @class: org.apereo.cas.ws.idp.services.WsFederationClaimsReleasePolicy

后台反序列化提示WsFederationClaimsReleasePolicy不是RegisteredServiceAttributeReleasePolicy的子类

MD 找了我一天,最后就改了一个字母,给官方发了pullrequest

js写的类名是Ws,后台JAVA写的是WS,已经给官方提了PR

https://github.com/apereo/cas-management/pull/160/files

记一次蜜汁BUG

hadoop任务出错

但是看userlog下无日志
追查好久后发现任务结束居然会自动删container的日志,MDZZ

然后使用watch -n 'cp -r ./* ..'把日志考出去

发现错误日志如下

????黑人问号,不过总算找到问题根源了
但是Insights.Ginkgo.2:35639这个地址咋了??
网上说是没配置jobhistory的地址,但是这个服务器是克隆的镜像啊,之前也没配置过啊
在mapred-site.xml加上下面的配置

搜了下这个名字在hadoop配置文件没找到
查了下当前主机hostname是Insights
而/etc/hosts写的是
127.0.0.1 localhost
127.0.1.1 Insights.Ginkgo.2 Insights

尝试改成这样重启hadoop再试
127.0.0.1 localhost
127.0.1.1 Insights Insights.Ginkgo.2

成功了!!!不过不知道是哪个影响的,需要后续再确认下

另外Insights数据分析配置中override.cfg,新的配置格式有点变化

注意pattern和source变成了json,反斜杠要转义一次的,但是也不能写\\\\否则读到pathutil.py中的正则会多一层转义,要写成图中的样子,这格式是re包的正则,不是shell中的正则,所以开头是.*不是*

spring jmstemplate的坑

jmstemplate 发送文本消息的写法
第一种手动构造msg的话不需要做特殊处理,但是很麻烦

调用方写法

第二种自动构造msg需要在注入bean的时候指定msgConverter,写法简洁但是需要注意不要做第手动转换

调用方写法

apache反向代理tomcat获取用户真实IP

校内CAS单点登录的审计日志中,用户的IP地址一直是服务器地址。这个问题拖了好久,今天终于解决了。
通过追查日志的来源,发现是自己实现了一个appender配置在了log4j中。
从这个类入手开始追查代码,最终发现IP的来源是通过request.getRemoteAddr这个方法来获得的。
而这个方法是来源于tomcat自身的servlet-api提供,返回的向tomcat发起请求的客户端IP。

但是一般情况下tomcat都会用nginx或apache代理tomcat,所以这个方法得到的IP就是服务器自身的IP而不是真实的远程IP了
而我又不想更改CAS的源码重新部署,所以只能想办法更改tomcat,让tomcat得到真实的IP。
根据apache文档所述,proxy模块会自动添加这三个header。
但是还差两个header没有添加,于是引入header模块使用下面的指令设置剩下的信息。
RequestHeader set x-forwarded-by “IP”
RequestHeader set x-forwarded-proto “https”
由于我的服务器是https协议,所以写了https。

根据tomcat文档所述,在tomcat端的server.xml中
Engine级别下添加Value节点。

文档写的很清楚internalProxies指定的正则所匹配的地址不会在x-forwarded-by中出现,而trustedProxied正则匹配的地址会出现在x-forwarded-by中。
我想要的结果是真实IP为用户IP,同时添加校内服务器的ip地址进入x-forwarded-by中,所以理论上我值需要把服务器IP地址段的正则写入trustedProxied即可。但是实际测试结果依然不对。
getRemoteAddr方法返回的依然是服务器的IP而不是真实IP。

而如果我在internalProxies服务器IP地址段正则的话,getRemoteAddr返回的结果就是正常的,但是x-forwarded-by字段就看不见代理服务器的IP了。

同时更改tomcat日志的格式如下。

Linux使用代理服务器的异常

今天在ZFZ的CAS测试环境下配置代理,配置环境变量https_proxy和http_proxy=’xxx.xxx.xxx.xxx:port’之后发现还是上不了网
但是我在windows上测试是正常的,说明代理服务器没问题。
而curl可以正常使用,只有sudo git clone 不行
我怀疑是root下没有这个环境变量,去root下改.bashrc后再测试还是不行
于是尝试把这两个环境变量写到系统级别,/etc/profile的最后,source /etc/profile了还是不行
查度娘后发现sudo之后环境变量需要配置,于是在/etc/sudoers
加了这么一行,成功
Defaults env_keep += “http_proxy https_proxy no_proxy”

HTTPS证书制作和配置示例

今天在校内尝试从git.bistu.edu.cn克隆代码,使用https协议时候发现clone失败,于是开始实验,使用curl连接cas.bistu.edu.cn、x.bistu.edu.cn、chat.bistu.edu.cn、community.bistu.edu.cn、site.bistu.edu.cn
发现只有cas和site正常,其他的都报错了,但是浏览器访问并未发现错误。
联想之前ZFZ的safari访问git报错而我电脑的浏览器却没事,瞬间意识到之前配置的HTTPS可能很多都有问题。
经过一翻折腾,发现之前的补链不全导致有些浏览器无法识别完整的信任链,最终通过补链解决。
当Apache、IIS、Nginx都不报错之后,只有Tomcat还有问题。
Tomcat之前的jks使用的是http://www.agentbob.info/agentbob/79-AB.html这篇文章的工具生成的,说明这个工具有问题。
继续搜索发现可以使用
openssl s_client -msg -connect cas.bistu.edu.cn:8443
这个命令来调试详细的ssl连接过程
和正常的过程对比发现Tomcat的信任链依然不一样。遂放弃这个工具。
最终在文末的文章中找到了解决方案。
废话说完了,下面是完整操作记录。
—————————————————————–
拿到手的有bistu.crt证书一张、bistu.key私钥一个。
实际需要开启HTTPS的服务器若干,服务器种类为Tomcat、Nginx、Apache、IIS。
到证书签发机构官网下载root根证书和中间证书,在windows上另存为Base64PEM格式
分别为root.crt和intermediate.crt
拷贝到Linux下开始制作

补链后证书为bistu.chained.crt

生成bistu.jks为tomcat所需格式

openssl pkcs12 -export -out bistu.pfx -inkey bistu.key -in bistu.crt

生成bistu.pfx为IIS所需格式

至此所有文件如下
1.bistu.crt #原始证书
2.bistu.key #私钥
3.root.crt #根证书
4.intermediate.crt #中间证书
5.bistu.chained.crt #补链后证书
6.combined.crt #中间链+根证书
7.bistu.p12 #p12格式的证书库
8.bistu.jks #jks格式的证书库
9.bistu.pfx #pfx格式的证书库

Apache需要的:1、2、5
Nginx需要的:2、5
Tomcat需要的:8
IIS需要的:2、9

配置示例

Apache

Nginx配置示例

Tomcat配置示例

参考:
http://blog.csdn.net/jun55xiu/article/details/8980812
http://www.fourproc.com/2010/06/23/create-a-ssl-keystore-for-a-tomcat-server-using-openssl-.html
https://blogs.oracle.com/blogbypuneeth/entry/steps_to_create_a_jks

gradle入门中文教程

—————————下面是废话,可以忽略—————————-
第一次见到gradle是在写Android的时Android Studio下方的提示,那时候还没有仔细研究。第二次是在搭建校内中央认证的时候,由于需要研究代码不得不从源码导入idea,但是官方只有一堆源码,没有任何idea的项目文件。idea的依赖是存在.idea文件夹下的xml中的,而这个项目的依赖都写在了gradle文件中,当时费了好多时间才把官方4.2.0的源码成功导入,手工解决各种依赖问题,我高估了idea,还以为它能解析gradle并自动识别各种依赖呢,事实证明它确实能导入,但是依赖的级别都是错的或者有丢失。(顺便吐槽一下,如果一个jar中的依赖缺失是不会报错的,手动微笑)
官方文档居然一点提示都没有→_→后来偶然发现build.gradle文件中有这么几行

瞬间脑洞大开,想到当时写QQ机器人时候用的boost库的安装,是先根据需要生成不同版本vs的sln文件再导入到vs中,怀疑这个会不会一样的套路。

由于还看不懂build.gradle的语法,但是大概猜到意思是所有的项目使用了这几个插件,于是去gradle文档翻了翻,果然看到了这个文档

原文:The IDEA plugin generates files that are used by IntelliJ IDEA, thus making it possible to open the project from IDEA (File – Open Project). Both external dependencies (including associated source and Javadoc files) and project dependencies are considered.
意思是说这个插件可以生成idea所需的文件,让这个项目可以通过idea打开。

啊~~我花了这么长时间都在干些啥,再次鄙视CAS官方没在4.2.x文档写清楚,咳咳
今天特意上去看了下,4.2.x的文档确实没写,臻不是我没看到。我有句XXX一定要讲!最新版本的文档在开发者一栏增加了Build Process的教程传送门

论写好文档的重要性T T虽然我也懒的写(逃

—————————上面是废话,可以忽略—————————-

扯了这么多废话还是说正事吧,咳咳。

1.安装

要求:gradle可以在当前主流的平台上运行,仅仅需要jre或jdk7以上就可以。
如果你已经有一个使用gradle生成的项目,并且使用了GradleWrapper的话,就不需要安装任何其他的东西了,只要运行gradlew这个shell脚本就可以了,windows下为gradlew.bat,这个脚本会下载项目对应的gradle版本。但是我不推荐使用,国内的网你懂得。
windows上手动安装只需要下载这个包(传送门)然后解压即可。记的把bin目录加到环境变量PATH中。

Ubuntu上更简单apt-get install gradle,不解释了。

安装完成后运行gradle -v检查版本。
另外官方支持Zsh和Bash的自动完成脚本(传送门)

2.基本使用

如果你用过linux的make编译软件,那么你会比较容易理解gradle,感觉很像。
新建一个文件夹,里面放入一个名为build.gradle的文件,内容如下:

依赖关系如图(不知道能不能直接用官方图。。。如果不能自己点开吧)
图片地址:https://docs.gradle.org/current/userguide/img/commandLineTutorialTasks.png

进入命令行执行gradle dist,输出如下

每一个任务都有自己的依赖,当任务自己不依赖其他任务时候,就可以开始执行了,按拓扑序列执行所有任务,直到指定的dist完成。
如果想跳过某个任务,使用-x参数,例如gradle dist -x test跳过了test任务

默认情况下,gradle执行时候如果碰到有任务失败就会停下来,如果你为了尽可能多的发现错误,可以使用--continue参数。这时候如果有某个任务的依赖执行失败,那么这个任务也会被跳过。

当执行命令行时,可以使用任务名简写,只要给出的名字能确定唯一任务就行。例如di指的是dist,cT指的是compTest。

gradle tasks用来列出可以执行的任务列表。
gradle help --task someTask 用来查看某个任务的详细说明。
gradle -m someTask 用来查看某个任务的执行顺序,但是并没有真的执行。

3.Gradle Wrapper

大多数工具在使用之前要求你安装一些东西,如果他们安装简单那是最好的。但是如果像Hadoop安装一样繁琐,你就会感觉好气啊,怎么还不能用。更重要的是版本问题,如果版本不兼容怎么办?Gradle Wrapper同时解决了这些问题。
如果一个项目使用了Wrapper(官方建议每个项目都用),你可以像上文提到的那样使用gradle 来执行构建任务。(虽然我不推荐,因为网速实在是感人)

每个Wrapper都知道自己应该下载什么版本的gradle,所以不用担心版本问题。
这些文件很重要,不能删
gradlew (Unix Shell script)
gradlew.bat (Windows batch file)
gradle/wrapper/gradle-wrapper.jar (Wrapper JAR)
gradle/wrapper/gradle-wrapper.properties (Wrapper properties)

当通过Wrapper导入IDE的时候,IDE会使用Gradle的all版本,这可以帮助IDE更好的完成代码补全(个人建议安装的时候就下载all版本)
Wrapper下载的Gradle默认存放位置为
linux上为~/.gradle/wrapper/dists
windows上为C:\Users\<你的用户名>\.gradle\wrapper\dists

4.Gradle Daemon

From Wikipedia:
A daemon is a computer program that runs as a background process, rather than being under the direct control of an interactive user.

从3.0开始Gradle默认会启动一个守护进程,来减少每次build时候启动JVM的时间,并且可以在内存缓存项目相关的信息。
使用gradle --status查看守护进程
使用gradle --stop停止守护进程
在gradle.properties文件中写入org.gradle.daemon=false,并把文件放在默认目录下即可禁用守护进程。
linux上为~/.gradle/wrapper/dists
windows上为C:\Users\<你的用户名>\.gradle\wrapper\dists

5.依赖管理

大概来说,依赖管理由两步组成。Gradle需要知道你构建或运行项目需要的东西。第一步:找到它们,我们把这些文件叫做项目的依赖。第二步:Gradle需要把这些文件编译链接重组结构到你的产品中,我们把生成的文件叫做项目产品。

大多数项目的编写或测试都需要依赖其他的项目,例如为了使用Hibernate,在编译时候我需要把一些jar文件包含到我的classpath中,为了运行单元测试我需要额外的JUnit的jar包,还有就是JDBC数据库驱动等

这些外部依赖可能是远程的、本地的、子项目的等,Gradle需要知道这些依赖信息,并且把他们加载进来,我们把这个过程叫做依赖解析。

下面这段说的是Gradle比Ant更NB,不翻译了=_=好累.
Note that this feature provides a major advantage over Ant. With Ant, you only have the ability to specify absolute or relative paths to specific jars to load. With Gradle, you simply declare the “names” of your dependencies, and other layers determine where to get those dependencies from. You can get similar behavior from Ant by adding Apache Ivy, but Gradle does it better.

通常项目的依赖也会有他们的依赖,例如Hibernate的核心要求其他的几个库来运行,所以当Gradle运行项目测试的时候也需要找到这些依赖的依赖,叫做传递依赖。

大多数项目的目的是生成其他项目可用的库,例如Java Library,你需要生成jar文件或者包括源码和文档的jar文件并且发布出去。我们把这个过程叫做发布。
下面大概说Gradle非常关心你的用户体验,它能帮你把产品发布到任何地方(中文的博大精深)。
These outgoing files form the publications of the project. Gradle also takes care of this important work for you. You declare the publications of your project, and Gradle take care of building them and publishing them somewhere. Exactly what “publishing” means depends on what you want to do. You might want to copy the files to a local directory, or upload them to a remote Maven or Ivy repository. Or you might use the files in another project in the same multi-project build. We call this process publication.

示例代码:

上面的脚本声明了项目编译时需要Hibernate core 3.6.7.Final版本,言外之意是在运行时依然需要Hibernate和它自身的依赖。同理在编译单元测试的时候依赖junut4.0以上版本。同时它告诉Gradle在Maven中心仓库寻找任何其他需要的依赖。

Gradle依赖是分组管理的,一个配置组代表了一系列的依赖,Java插件定义了一系列标准配置。详见这篇文档

compile 这些依赖在编译时需要。
runtime 这些依赖在运行时需要,默认情况下已经包含了compile依赖。
testCompile 这些依赖在编译测试代码时需要。默认情况下也包含了所有编译后的class文件和compile依赖。
testRuntime 这些依赖在运行测试时候需要,默认情况下包含上面3个所有的依赖。

许多组件添加了很多标准配置,你可以定义你自己的配置,详见这篇文档.

示例:
外部依赖声明

第二个写法是简写
关于仓库设置不再啰嗦:原文传送门

(未完待续。。。。)

参考:http://wiki.jikexueyuan.com/project/GradleUserGuide-Wiki/
https://gradle.org/docs
https://gradle.org/getting-started-gradle/
https://docs.gradle.org/3.3/dsl/index.html
https://gradle.org/install
https://gradle.org/getting-started/creating-a-build
https://docs.gradle.org/current/userguide/userguide.html
http://www.cnblogs.com/davenkin/p/gradle-learning-1.html
http://blog.jobbole.com/71999/
http://blog.jobbole.com/72558/
http://blog.jobbole.com/72992/