国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html
内部邀请码:C8E245J (不写邀请码,没有现金送)
国内私募机构九鼎控股打造,九鼎投资是在全国股份转让系统挂牌的公众公司,股票代码为430719,为“中国PE第一股”,市值超1000亿元。 
------------------------------------------------------------------------------------------------------------------------------------------------------------------

原文地址: http://denger.iteye.com/blog/973068

最近因为公司另一款基于C/S的产品也需要整合到CAS 的 SSO,但是 CAS 本身对于客户端或浏览器而言是基于其COOKIE来存储用户(TGT)Ticket的,所以这时候就需要使用 CAS 的 RestFul API 来进行登录验证,并支持在C/S软件中点击用户头象时打开浏览器并跳转至用户中心,而且这时候在 WEB 上应该是已登录的状态(类似QQ点击自己的头象时,马上就进入到了QQ空间。)

关于CAS的登录验证流程,可以参考“CAS 之 实现用户注册后自动登录”,这里的RESTful登录验证流程与其大致相似,大体流程为:首先客户端提交用户名、密码、及Service三个参数,如果验证成功便返回用户的TGT(Ticket Granting Ticket)至客户端, 然后客户端再根据 TGT 获取用户的 ST(Service Ticket)来进行验证登录。 故名思意,TGT是用于生成一个新的Ticket(ST)的Ticket,而ST则是提供给客户端用于登录的Ticket,两者最大的区别在于,TGT是用户名密码验证成功之后所生成的Ticket,并且会保存在Server中及Cookie中,而ST则必须是是根据TGT来生成,主要用于登录,并且当登录成功之后 ST 则会失效。

CAS本身已经提供了 restlet 的集成包,如果你用的是 maven 的话直接加入,我这里的Cas-server的版本是 3.4.2.1:

  1. <dependency>
  2. <groupId>org.jasig.cas</groupId>
  3. <artifactId>cas-server-integration-restlet</artifactId>
  4. <version>3.4.2.1</version>
  5. <type>jar</type>
  6. </dependency>

然后再在 web.xml 中加入:

  1. <servlet>
  2. <servlet-name>restlet</servlet-name>
  3. <servlet-class>com.noelios.restlet.ext.spring.RestletFrameworkServlet</servlet-class>
  4. <load-on-startup>1</load-on-startup>
  5. </servlet>
  6. <servlet-mapping>
  7. <servlet-name>restlet</servlet-name>
  8. <url-pattern>/v1/*</url-pattern>
  9. </servlet-mapping>

因为使用到了 Restlat 框架,所以还需要依赖几个 jar 包,分别是:

  • com.noelios.restlet.ext.servlet.jar
  • com.noelios.restlet.ext.spring-1.1.0.jar
  • com.noelios.restlet.jar
  • org.restlet-1.1.10.jar
  • org.restlet.ext.spring-1.1.10.jar

这几个jar已经打包在附件中了,另外 restlet.org 的 maven库中也有,需要的话可以去 maven.restlet.org 上找。
   另外关于 restlet的配置在 cas-server中已经存在在: /WEB-INF/restlet-servlet.xml文件。

配置OK之后直接启动Server,下面来进行简单登录验证的测试:

1. 提交用户名密码及Service 进行登录验证

  1. DengerMacBook:cas-server denger$ curl -i -X  POST -d "username=admin&password=123456&service=http://www.google.com" http://192.168.41.107:8080/member/v1/tickets/
  2. HTTP/1.1 201 Created
  3. Date: Wed, 23 Mar 2011 12:42:52 GMT
  4. Location: http://192.168.41.107:8080/member/v1/tickets/TGT-14-gDOn9hhSYmq3xfeTRNhTAjZgOMdCdyuVNfsuLRs6onNv7fVmmX-cas
  5. Accept-Ranges: bytes
  6. Server: Noelios-Restlet-Engine/1.1.6
  7. Content-Type: text/html;charset=ISO-8859-1
  8. Content-Length: 437
  9. <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"><html><head><title>201 The request has been fulfilled and resulted in a new resource being created</title></head><body><h1>TGT Created</h1><form action="http://192.168.41.107:8080/member/v1/tickets/TGT-14-gDOn9hhSYmq3xfeTRNhTAjZgOMdCdyuVNfsuLRs6onNv7fVmmX-cas" method="POST">Service:<input type="text" name="service" value=""><br><input type="submit" value="Submit"></form></body></html>

在以上Response信息及 Header中可以看到生成的 TGT,接下来是再重新根据 TGT 获取 ST,将请求的 URI 地址就是以上 Header中的 Location地址。

2. 根据返回的 TGT 来获取 ST

  1. DengerMacBook:cas-server denger$ curl -i  -X POST -d "service=http://www.google.com" http://192.168.41.107:8080/member/v1/tickets/TGT-14-gDOn9hhSYmq3xfeTRNhTAjZgOMdCdyuVNfsuLRs6onNv7fVmmX-cas
  2. HTTP/1.1 200 OK
  3. Date: Wed, 23 Mar 2011 12:48:03 GMT
  4. Accept-Ranges: bytes
  5. Server: Noelios-Restlet-Engine/1.1.6
  6. Content-Type: text/plain;charset=ISO-8859-1
  7. Content-Length: 29
  8. ST-2-lJfQyJMMEnNGnKcglf1d-cas

获取成功之后则返回了 ST,这时候对于客户端而言就已经拿到了登录的TIcket, 如果需要在Web中自动登录的话,只需要弹出浏览器,将ST作为 ticket参数传入即可。如,用户中心的后台地址首页是:http://www.google.com.hk/userCenter 则URL为:  http://www.google.com.hk/userCenter?ticket=ST-3-9QkpLsFmCEqIXSVvGH9P-cas 并可进行登录。 当然前提是在该Web应用中需要部署cas-client应用。

3. 注销用户

  1. DengerMacBook:cas-server denger$ curl -i  -X DELETE http://192.168.41.107:8080/member/v1/tickets/TGT-14-gDOn9hhSYmq3xfeTRNhTAjZgOMdCdyuVNfsuLRs6onNv7fVmmX-cas
  2. HTTP/1.1 200 OK
  3. Date: Wed, 23 Mar 2011 12:54:28 GMT
  4. Accept-Ranges: bytes
  5. Server: Noelios-Restlet-Engine/1.1.6
  6. Content-Length: 0

注销用户就很简单了,直接 SUBMIT DELETE 删除 TGT即可.

Java代码调用示例:

  1. package cas;
  2. import java.io.IOException;
  3. import java.util.logging.Logger;
  4. import java.util.regex.Matcher;
  5. import java.util.regex.Pattern;
  6. import org.apache.commons.httpclient.HttpClient;
  7. import org.apache.commons.httpclient.NameValuePair;
  8. import org.apache.commons.httpclient.methods.PostMethod;
  9. public final class Client
  10. {
  11. private static final Logger LOG = Logger.getLogger(Client.class.getName());
  12. private Client()
  13. {
  14. // static-only access
  15. }
  16. public static String getTicket(final String server, final String username,
  17. final String password, final String service)
  18. {
  19. notNull(server, "server must not be null");
  20. notNull(username, "username must not be null");
  21. notNull(password, "password must not be null");
  22. notNull(service, "service must not be null");
  23. return getServiceTicket(server, getTicketGrantingTicket(server, username,
  24. password), service);
  25. }
  26. private static String getServiceTicket(final String server,
  27. final String ticketGrantingTicket, final String service)
  28. {
  29. if (ticketGrantingTicket == null)
  30. return null;
  31. final HttpClient client = new HttpClient();
  32. final PostMethod post = new PostMethod(server + "/" + ticketGrantingTicket);
  33. post.setRequestBody(new NameValuePair[] { new NameValuePair("service",
  34. service) });
  35. try
  36. {
  37. client.executeMethod(post);
  38. final String response = post.getResponseBodyAsString();
  39. switch (post.getStatusCode())
  40. {
  41. case 200:
  42. return response;
  43. default:
  44. LOG.warning("Invalid response code (" + post.getStatusCode()
  45. + ") from CAS server!");
  46. LOG.info("Response (1k): "
  47. + response.substring(0, Math.min(1024, response.length())));
  48. break;
  49. }
  50. }
  51. catch (final IOException e)
  52. {
  53. LOG.warning(e.getMessage());
  54. }
  55. finally
  56. {
  57. post.releaseConnection();
  58. }
  59. return null;
  60. }
  61. private static String getTicketGrantingTicket(final String server,
  62. final String username, final String password)
  63. {
  64. final HttpClient client = new HttpClient();
  65. final PostMethod post = new PostMethod(server);
  66. post.setRequestBody(new NameValuePair[] {
  67. new NameValuePair("username", username),
  68. new NameValuePair("password", password) });
  69. try
  70. {
  71. client.executeMethod(post);
  72. final String response = post.getResponseBodyAsString();
  73. switch (post.getStatusCode())
  74. {
  75. case 201:
  76. {
  77. final Matcher matcher = Pattern.compile(".*action=\".*/(.*?)\".*")
  78. .matcher(response);
  79. if (matcher.matches())
  80. return matcher.group(1);
  81. LOG
  82. .warning("Successful ticket granting request, but no ticket found!");
  83. LOG.info("Response (1k): "
  84. + response.substring(0, Math.min(1024, response.length())));
  85. break;
  86. }
  87. default:
  88. LOG.warning("Invalid response code (" + post.getStatusCode()
  89. + ") from CAS server!");
  90. LOG.info("Response (1k): "
  91. + response.substring(0, Math.min(1024, response.length())));
  92. break;
  93. }
  94. }
  95. catch (final IOException e)
  96. {
  97. LOG.warning(e.getMessage());
  98. }
  99. finally
  100. {
  101. post.releaseConnection();
  102. }
  103. return null;
  104. }
  105. private static void notNull(final Object object, final String message)
  106. {
  107. if (object == null)
  108. throw new IllegalArgumentException(message);
  109. }
  110. public static void main(final String[] args)
  111. {
  112. final String server = "http://192.168.41.107:8080/member/v1/tickets";
  113. final String username = "admin";
  114. final String password = "111111";
  115. final String service = "http://localhost:8080/service";
  116. LOG.info(getTicket(server, username, password, service));
  117. }
  118. }

参考:https://wiki.jasig.org/display/CASUM/RESTful+API

 

CAS 之 集成RESTful API的更多相关文章

  1. springboot集成swagger2,构建优雅的Restful API

    swagger,中文“拽”的意思.它是一个功能强大的api框架,它的集成非常简单,不仅提供了在线文档的查阅,而且还提供了在线文档的测试.另外swagger很容易构建restful风格的api,简单优雅 ...

  2. (转)第十一篇:springboot集成swagger2,构建优雅的Restful API

    声明:本部分内容均转自于方志明博友的博客,因为本人很喜欢他的博客,所以一直在学习,转载仅是记录和分享,若也有喜欢的人的话,可以去他的博客首页看:http://blog.csdn.net/forezp/ ...

  3. (转) SpringBoot非官方教程 | 第十一篇:springboot集成swagger2,构建优雅的Restful API

    swagger,中文“拽”的意思.它是一个功能强大的api框架,它的集成非常简单,不仅提供了在线文档的查阅,而且还提供了在线文档的测试.另外swagger很容易构建restful风格的api,简单优雅 ...

  4. springboot集成swagger2构建RESTful API文档

    在开发过程中,有时候我们需要不停的测试接口,自测,或者交由测试测试接口,我们需要构建一个文档,都是单独写,太麻烦了,现在使用springboot集成swagger2来构建RESTful API文档,可 ...

  5. SpringBoot非官方教程 | 第十一篇:springboot集成swagger2,构建优雅的Restful API

    转载请标明出处: 原文首发于:https://www.fangzhipeng.com/springboot/2017/07/11/springboot-swagger2/ 本文出自方志朋的博客 swa ...

  6. 【Tech】CAS RESTful API使用笔记

    在被maven,cas,tomcat各种贱人就是矫情的虐了好几天之后,终于跑通了demo,哈哈哈哈哈哈哈~ 在这里详细记录一下,给和我一样连maven都不会的小白一点福利,同时欢迎大神指正. 首先上最 ...

  7. Spring Boot 集成Swagger2生成RESTful API文档

    Swagger2可以在写代码的同时生成对应的RESTful API文档,方便开发人员参考,另外Swagger2也提供了强大的页面测试功能来调试每个RESTful API. 使用Spring Boot可 ...

  8. 集成swagger2构建Restful API

    集成swagger2构建Restful API 在pom.xml中进行版本管理 <swagger.version>2.8.0</swagger.version> 给taosir ...

  9. Spring Boot 集成 Swagger 生成 RESTful API 文档

    原文链接: Spring Boot 集成 Swagger 生成 RESTful API 文档 简介 Swagger 官网是这么描述它的:The Best APIs are Built with Swa ...

随机推荐

  1. Seven Python Tools All Data Scientists Should Know How to Use

    Seven Python Tools All Data Scientists Should Know How to Use If you’re an aspiring data scientist, ...

  2. unity Android 打包后读取 xml 文件

    原地址:http://www.cnblogs.com/wuzhang/p/wuzhang20140731.html 问题:    前天在做东西的过程中发现了一个让人很纠结的问题,为什么Unity 程序 ...

  3. Navicat 导入导出

    当我们对mysql数据库进行了误操作,造成某个数据表中的部分数据丢失时,肯定就要利用备份的数据库,对丢失部分的数据进行导出.导入操作了.Navicat工具正好给我们提供了一个数据表的导入导出功能. 1 ...

  4. Two-Phase Locking

    两阶段封锁(Two-Phase Locking) 两段锁协议的内容 1. 在对任何数据进行读.写操作之前,事务首先要获得对该数据的封锁 2. 在释放一个封锁之后,事务不再获得任何其他封锁. “两段”锁 ...

  5. 近期会放出tlplayer for android的更新版本

    tlplayer for android的一次重大更新在近期将会放出,自从去年初的时候放出tlplayer android版本后,一直都没有更新tlplayer,而tlplayer for windo ...

  6. 应付描述性弹性域 Description Flexfield

    (N) AP > Setup > Flexfield > Description > Segments To define your descriptive flexfield ...

  7. hdu4714Tree2cycle

    链接 树上的一些操作还是不是太好想 直接dfs下去 不是最优的 一个节点最多保留两个度 如果它有两个以上的子节点 那么就与父节点断开 与k-2个子节点断开 再重新连 #pragma comment(l ...

  8. cat ,more, Less区别

    使用cat more less都可以查看文本内容,但是它们三者有什么区别呢?more和less的功能完全重复吗?以下是我个人的总结,欢迎大家一起来分享 cat        连续显示.查看文件内容mo ...

  9. BZOJ_3207_花神的嘲讽计划1_(Hash+主席树)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=3207 给出一个长度为\(n\)的串,以及\(m\)个长度为\(k\)的串,求每个长度为\(k\ ...

  10. vijosP1567子串计数

    描述现在有一个字符串,请求出这个字符串不相同的子串个数.YXY现在不会做,请你来帮忙…… n<=20W 题解: 后缀数组裸题,其实我在练习模板写对了没 代码: #include<cstdi ...