国内私募机构九鼎控股打造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. GCC 警告提示的用法

    转自GCC 警告提示的用法 本节主要讲解GCC的警告提示功能.GCC包含完整的出错检查和警告提示功能,它们可以帮助Linux程序员写出更加专业和优美的代码.我们千万不能小瞧这些警告信息,在很多情况下, ...

  2. PYTHON多进程样码

    敲了一晚上,留个念想. 发现它和LINUX的C编程差不多,就是作了PYTHON化的语法封装. 以后希望有机会能用上.. A,多进程函数化实现 import multiprocessing import ...

  3. JavaScript 判断是否为undefined

    if (typeof(reValue) == "undefined") {    alert("undefined"); }

  4. UVALive - 3713 Astronauts

    给定n个宇航员的年龄,平均年龄为 ave,根据下列要求分配任务: B任务只能分配给年龄<ave的宇航员: A任务只能分配给年龄>=ave的宇航员: C任务可以任意分配. 给定m组互相憎恨的 ...

  5. char和QChar(Unicode的编码与内存里的值还不是一回事)

    char类型是c/c++中内置的类型,描述了1个字节的内存信息的解析.比如: char gemfield=’g’; 那么在由gemfield标记的这块内存的大小就是1个字节,信息就是01100111, ...

  6. QAbstractItemView为截断的项显示ToolTip(在eventFilter函数里覆盖QEvent::ToolTip事件)

    在Qt中想要为QAbstractItemView中长度不够而使得内容被截断的项显示ToolTip,Qt官网有一篇文章介绍使用事件过滤器来显示太长的项,但是没有涵盖图标的情况.显示列头项太长的情况等等, ...

  7. 【Linux远程管理】SSH协议远程管理

    SSH(Secure Shell)协议.命令行界面(CLI)下的远程管理工具,几乎所有的操作系统都有,区别于Telnet,SSH在进行数据传送时会对数据进行加密,所以SSH是比较安全的协议.几乎所有的 ...

  8. linux下 修改配置文件的命令

    vi或vim 进入后,按i,屏幕下方会出现INSERT字样,此时可以修改内容 按ESC,退回命令模式 :x是保存退出 :q!是不保存退出

  9. Linux内核中流量控制

    linux内核中提供了流量控制的相关处理功能,相关代码在net/sched目录下:而应用层上的控制是通过iproute2软件包中的tc来实现, tc和sched的关系就好象iptables和netfi ...

  10. [Hadoop源码解读](三)MapReduce篇之Job类

    下面,我们只涉及MapReduce 1,而不涉及YARN. 当我们在写MapReduce程序的时候,通常,在main函数里,我们会像下面这样做.建立一个Job对象,设置它的JobName,然后配置输入 ...