国内私募机构九鼎控股打造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. 年度十佳 DevOps 博客文章(前篇)

    如果说 15 年你还没有将 DevOps 真正应用起来,16 年再不实践也未免太落伍了.国内 ITOM 领军企业 OneAPM 工程师为您翻译整理了,2015 年十佳 DevOps 文章,究竟是不是深 ...

  2. Java使用socket实现两人聊天对话

    import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner; /* ...

  3. 安装java memcached client到本地maven repository

    由于目前java memcached client没有官方的maven repository可供使用,因此使用时需要手动将其安装到本地repository.java memcached client的 ...

  4. Android ListView(Selector 背景图片)

    listview0.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmln ...

  5. 了解实时媒体的播放(RTP/RTCP 和 RTSP)

    http://blog.csdn.net/span76/article/details/12913307 RTP/RTCP RTP是基于 UDP协议的, UDP不用建立连接,效率更高:但允许丢包, 这 ...

  6. 如何忽略usb host 模式设备连接确认对话框

    <li class="alt"><span><span>package android.hardware.usb;  </span> ...

  7. Sql server decimal 和 numeric

    带固定精度和小数位数的数值数据类型. decimal[ (p[ , s] )] 和 numeric[ (p[ , s] )] 固定精度和小数位数.使用最大精度时,有效值从 - 10^38 +1 到 1 ...

  8. Android 如何在ScrollView中嵌套ListView

    前几天因为项目的需要,要在一个ListView中放入另一个ListView,也即在一个ListView的每个ListItem中放入另外一个ListView.但刚开始的时候,会发现放入的小ListVie ...

  9. php陷阱:字符串和数字比较

    PHP中的比较运算符有点诡异,很容易出错,现列出比较规则: 1.当两个字符进行大小比较时,是比较着这两个字符的ASCII码大小——这条很容易理解. 2.当两个字符串进行大小比较时,是从第一个字符开始, ...

  10. mysql导出csv/excel文件的几种方法,mysql的load导入csv数据

    方法一 php教程用mysql的命令和shell select * into outfile './bestlovesky.xls' from bestlovesky where 1 order by ...