gaojingsong http://doc.okbase.net/gaojingsong 【lanproxy 介绍】 http://doc.okbase.net/gaojingsong/archive/265579.html gaojingsong 2017/11/19 14:43:55

lanproxy是一个将局域网个人电脑、服务器代理到公网的内网穿透工具,目前仅支持tcp流量转发,可支持任何tcp上层协议(访问内网网站、本地支付接口调试、ssh访问、远程桌面...)。目前市面上提供类似服务的有花生壳、TeamView、GoToMyCloud等等,但要使用第三方的公网服务器就必须为第三方付费,并且这些服务都有各种各样的限制,此外,由于数据包会流经第三方,因此对数据安全也是一大隐患。 


 

 

 

server配置

server的配置文件放置在conf目录中,配置 config.properties

server.bind=0.0.0.0

#与代理客户端通信端口
server.port=4900

#ssl相关配置
server.ssl.enable=true
server.ssl.bind=0.0.0.0
server.ssl.port=4993
server.ssl.jksPath=test.jks
server.ssl.keyStorePassword=123456
server.ssl.keyManagerPassword=123456
server.ssl.needsClientAuth=false

#WEB在线配置管理相关信息
config.server.bind=0.0.0.0
config.server.port=8090
config.admin.username=admin
config.admin.password=admin

代理配置,打开地址 http://ip:8090 ,使用上面配置中配置的用户名密码登录

 

 

 

client配置

client的配置文件放置在conf目录中,配置 config.properties

#与在proxy-server配置后台创建客户端时填写的秘钥保持一致;没有服务器可以登录 https://lanproxy.org/ 创建客户端获取秘钥
client.key=
ssl.enable=true
ssl.jksPath=test.jks
ssl.keyStorePassword=123456

#这里填写实际的proxy-server地址;没有服务器默认即可,自己有服务器的更换为自己的proxy-server(IP)地址
server.host=lp.thingsglobal.org

#proxy-server ssl默认端口4993,默认普通端口4900
#ssl.enable=true时这里填写ssl端口,ssl.enable=false时这里填写普通端口
server.port=4993
  • 大小: 36.6 KB
]]> 【Docker 命令集】 http://doc.okbase.net/gaojingsong/archive/265492.html gaojingsong 2017/10/31 8:08:40
Docker 命令集
  attach   commit   diff     export   history import  insert    kill       login   port    
  pull       restart    rmi     save      start    tag       version  build   cp       events  
  help      images  info     inspect  load     logs     ps         push   rm       run     
  search  stop       top     wait
 
docker help: 
  docker help [COMMAND]
  例: docker help run
   docker version: 显示Docker版本
   docker info: 显示Docker信息
 
docker attach: 挂载正在后台运行的容器到前台
  docker attach [OPTIONS] Container
 
docker run: 在一个新的容器中执行命令 (CTRL-p CTRL-q 退出至后台运行)
  docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
  例:
  sudo docker run -i -t ubuntu:14.04 /bin/bash         启动一个新的Ubuntu容器
  sudo docker run --rm -i -t ubuntu:14.04/bin/bash   建议新手测试加上 -—rm
  sudo docker run -i -t --name "private_container" ubuntu:14.04 /bin/bash
 
docker ps: 列出当前容器
  docker ps [OPTIONS]
  命令参数:
  -a, --all=false            显示所有容器,包括当前没有运行的容器
  -f, --filter=[]               按条件过滤容器, 可选的过滤选项:
  exited=<int> 容器的返回值
  -l, --latest=false       显示最新的一个容器
  -n num  显示最新的N个容器
  --no-trunc=false       不要截断输出
  -q, --quiet=false       仅显示容器ID
  -s, --size=false        显示容器大小
  例:
  docker ps                              当前正在运行的容器
  docker ps -a                          当前正在运行或是停止的容器
  docker ps -a -q --no-trunc    获得当前所有容器的ID,不截断输出
  docker rm $(echo $(docker ps -q --no-trunc) $(dockerps -a -q--no-trunc) | sed 's|\s|\n|g' |sort | uniq -u)
  删除当前不在运行状态的容器ID,也可以把前面改成docker rm
 
docker images: 列出当前镜像
  docker images [OPTIONS] [NAME]
  命令参数:
  -a, --all=false            显示所有镜像,包括中间生成的临时镜像
  -f, --filter=[]               通过标签过滤 (i.e. 'dangling=true')
  --no-trunc=false        不要截断输出
  -q, --quiet=false        仅显示容器ID
  例子:
  docker images                                   显示当前仓库中的镜像
  docker images -a                               显示当前仓库中的镜像与临时镜像
  docker images -a -q --no-trunc        显示当前仓库中的镜像与临时镜像的ID,不截断输出
 
docker logs: 显示容器的日志
  docker logs CONTAINER
  命令参数:
  -f, --follow=false               等待容器后续的输出(类似 tail -f)
  -t, --timestamps=false     显示时间戳
  --tail="all"
  例:
  sudo docker logs 7bb0e258aefe
  sudo docker logs --timestamps=true 7bb0e258aefe
  sudo docker logs --timestamps=true 7bb0e258aefe > 7bb0e258aefe.log
  终端A:
  sudo docker logs --follow 7bb0e258aefe
  终端B:
  sudo docker attach 708cc7ec0f23         (随便执行一些命令可以看到终端A会有实时输出)
 
docker inspect: 显示镜像或容器的详细信息
  docker inspect CONTAINER|IMAGE [CONTAINER|IMAGE...]
  命令参数:
  -f, --format=""                  选择输出内容,--format="{{.NetworkSettings.IPAddress}}"
  例子:
  sudo docker inspect 7bb0e258aefe
  sudo dockerinspect --format "{{.State.Pid}}" 7bb0e258aefe
 
docker stop: 停止运行中的容器 (CTRL-d 强制退出, Exited (0))
  Docker stop [OPTIONS] CONTAINER [CONTAINER...]
  命令参数:
  -t, --time=10                    杀掉容器进程之前,等待的时间
  例子:
  sudo docker stop 7bb0e258aefe
 
docker kill: 杀掉一个运行中的容器 (Exited (-1))
  docker kill [OPTIONS] CONTAINER [CONTAINER...]
  命令参数:
  - s, --signal="KILL"          选择向容器发出的Signal
  例子:
  sudo docker kill 7bb0e258aefe
 
docker start: 重启停止的容器
  Docker start CONTAINER [CONTAINER...]
  命令参数:
  -a,--attach=false         Attach container'sSTDOUT and STDERR and forward allsignals to the process
  -i,--interactive=false   Attach container'sSTDIN
  例子:
  sudo docker start 7bb0e258aefe
 
docker restart: 重启运行中的容器
  d ocker restart [OPTIONS] CONTAINER [CONTAINER...]
  命令参数:
  -t, --time=10                     杀掉容器进程之前,等待的时间
  例子:
  sudo docker restart 7bb0e258aefe
 
 
docker cp: 拷贝容器中的文件
  docker cp CONTAINER:PATH HOSTPATH
  例子:
  docker cp c3f279d17e0a:/home/hyzhou/answer.txt .  将镜像中的/home/hyzhou/answer.txt文件拷贝到当前目录下
 
docker rm: 删除容器
  docker rm [OPTIONS] CONTAINER [CONTAINER...]
  命令参数:
  -f, --force=false              强制删除容器(使用SIGKILL)
  -l, --link=false                 Removethe specified link and not the underlyingcontainer
  -v, --volumes=false        Removethe volumes associated with the container
  例子:
  docker rm my_ubuntu               删除容器
  docker rm 708cc7ec0f23           删除容器
  docker rm $(docker ps -a -q)    删除所有容器
 
docker top: 查看容器输出
  docker top CONTAINER [ps OPTIONS]
  例子:
  [ps OPTIONS]的意思是, 你可以在这个命令后面加上使用ps命令时的各种参数
  sudo docker top 708cc7ec0f23
  sudo docker top 708cc7ec0f23 aux
 
docker events: 实时监听容器的事件
  docker events [OPTIONS]
  命令参数:
  --since=""                      显示某一个时间戳之后的events
  --until=""                        实时监听到某个时间戳为止
  例子:
  A终端:
  sudo docker events                             终端A等待Docker系统信息
  sudo docker events --since 1378216169
  sudo docker events --since '2013-09-03'
  sudo docker events--since '2013-09-03 15:49:29'
  sudo docker events --since'2013-09-03 15:49:29 +0200CEST'
  sudo docker events > docker.log &   后台记录Docker的容器事件
  B终端:
  sudo docker restart 708cc7ec0f23     从B终端关闭容器
  A终端显示:
  2014-09-06T23:08:21+08:00708cc7ec0f23a5ec898c9d6308e9767edb66b863e96352ca6e030f0a5557f3b2:(fromubuntu:latest) die
  2014-09-06T23:08:22+08:00708cc7ec0f23a5ec898c9d6308e9767edb66b863e96352ca6e030f0a5557f3b2:(fromubuntu:latest) start
  2014-09-06T23:08:22+08:00708cc7ec0f23a5ec898c9d6308e9767edb66b863e96352ca6e030f0a5557f3b2:(fromubuntu:latest) restart
 
 
docker history: 显示镜像的历史记录
  docker history [OPTIONS] IMAGE
  命令参数:
  --no-trunc=false              不要截断输出
  -q, --quiet=false              仅显示容器ID
 
docker search: 在Docker Hub上寻找镜像
  docker search TERM
  命令参数:
  --automated=false         使用Github或BitBucket的源代码自动构建
  --no-trunc=false             不要截断输出
  -s, --stars=0                   只显示Star数量超过N的镜像
  例子:
  docker search --starts=10 ubuntu
 
docker pull: 从远程拉取镜像
  docker pull NAME[:TAG]
  例子:
  docker pull ubuntu:latest
 
docker push: 推送镜像到远程仓库
  docker push NAME[:TAG]
  例子:
  docker push hyzhou/ubuntu:3.2.3
 
docker diff: 列出镜像中文件和目录的变化
  docker diff CONTAINER
  命令输出: 输出一共有三种
  A- Add
  D- Delete
  C- Change
  例子:
  diff显示的是镜像和当前运行的容器之间的区别,所以diff的基础是IMAGE
  下面例子中的b705fc4f4a50和708cc7ec0f23,内容其实是一样的
  sudo docker ps -a
  CONTAINERID        IMAGE                    COMMAND                CREATED             STATUS
  b705fc4f4a50        new:latest               "/bin/bash"            49 seconds ago      Up 49 seconds
  708cc7ec0f23        ubuntu:latest            "/bin/bash"            9 minutes ago       Up 9 minutes
  sudo docker diff 7bb0e258aefe
  C/root
  A/root/new.txt
  sudo docker diff b705fc4f4a50
 
docker commit: 将容器打包成新的镜像
  docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
  命令参数:
  -a, --author=""                 作者信息,"John Hannibal Smith <hannibal@a-team.com>"
  -m, --message=""            提交信息
  -p, --pause=true             在提交镜像时暂停容器
  例子:
  sudo docker ps
  ID                  IMAGE               COMMAND             CREATED             STATUS
  c3f279d17e0a        ubuntu:12.04        /bin/bash           7 days ago          Up 25 hours
  197387f1b436        ubuntu:12.04        /bin/bash           7 days ago          Up 25 hours
  docker commitc3f279d17e0a Hyzhou/my_ubuntu:3.2.3
  docker commit -a "Hyzhou<hyzhou@qq.com>" -m "addthe new software" c3f279d17e0aHyzhou/my_ubuntu:3.2.3
  docker images
  REPOSITORY                        TAG                 ID                  CREATED             VIRTUAL SIZE
  Hyzhou/my_ubuntu                  3.2.3               f5283438590d        16 seconds ago      335.7 MB
 
docker build: 使用Dockerfile构建新镜像
  docker build [OPTIONS] PATH|URL|-
  命令参数:
  --force-rm=false              移除构建时生成的中间容器
  --no-cache=false             Donot use cache when building the image
  -q, --quiet=false               不显示容器的输出
  --rm=true                         构建成功后,移除构建时生成的中间容器
  -t, --tag=""                        构建成功后,新建镜像的名称
 
docker tag: 为镜像加上标签
  docker tag [OPTIONS] IMAGE[:TAG][REGISTRYHOST/][USERNAME/]NAME[:TAG]
  命令参数:
  -f, --force=false                强制打上标签?
  例子:
  sudo docker tag ubuntu:latest hyzhou/my_ubuntu:3.2.3    给ubuntu:latest打上新TAG:hyzhou/my_ubuntu:3.2.3
  sudo dockertag eb601b8965b8 ubuntu:latest             给eb601b8965b8镜像打上TAG: ubuntu:latest(会转换原有的TAG指向)
 
  docker save: 将image保存为tar压缩文件
  docker save [OPTIONS] IMAGE [IMAGE...]
  -o, --output=""                  写入到一个文件中作为输出,默认是标准输出流
  例子:
  docker save --output ubuntu.tar ubuntu:latest  将Ubuntu的最新镜像打包为ubuntu.tar
  docker save ubuntu:latest > ubuntu.tar          将Ubuntu的最新镜像打包为ubuntu.tar
 
docker load: 将tar压缩文件保存为image
  Docker load [OPTIONS]
  命令参数:
  -i, --input=""                    读取一个压缩文件作为输入,默认是标准输入流
  例子:
  docker load --input ubuntu.tar                  读取ubuntu.tar作为镜像
  docker load < ubuntu.tar                        读取ubuntu.tar作为镜像
 
docker export: 把容器系统文件打包并导出来,方便分发给其他场景使用。
  docker export CONTAINER
  例子:
  sudo docker export my_ubuntu > ubuntu.tar       将Ubuntu的最新镜像打包为ubuntu.tar
 
docker import: 加载容器系统文件
  docker import URL|- [REPOSITORY[:TAG]]
]]>
【关于线程7种同步方式】 http://doc.okbase.net/gaojingsong/archive/265489.html gaojingsong 2017/10/31 8:08:09

1、锁的原理

Java中每个对象都有一个内置锁

当程序运行到非静态的synchronized同步方法上时,自动获得与正在执行代码类的当前实例(this实例)有关的锁。获得一个对象的锁也称为获取锁、锁定对象、在对象上锁定或在对象上同步。

当程序运行到synchronized同步方法或代码块时才该对象锁才起作用。

 

一个对象只有一个锁。所以,如果一个线程获得该锁,就没有其他线程可以获得锁,直到第一个线程释放(或返回)锁。这也意味着任何其他线程都不能进入该对象上的synchronized方法或代码块,直到该锁被释放。

 

释放锁是指持锁线程退出了synchronized同步方法或代码块。

 

关于锁和同步,有一下几个要点:

1)、只能同步方法,而不能同步变量和类;

2)、每个对象只有一个锁;当提到同步时,应该清楚在什么上同步?也就是说,在哪个对象上同步?

3)、不必同步类中所有的方法,类可以同时拥有同步和非同步方法。

4)、如果两个线程要执行一个类中的synchronized方法,并且两个线程使用相同的实例来调用方法,那么一次只能有一个线程能够执行方法,另一个需要等待,直到锁被释放。也就是说:如果一个线程在对象上获得一个锁,就没有任何其他线程可以进入(该对象的)类中的任何一个同步方法。

5)、如果线程拥有同步和非同步方法,则非同步方法可以被多个线程自由访问而不受锁的限制。

6)、线程睡眠时,它所持的任何锁都不会释放。

7)、线程可以获得多个重进入(synchronized )锁。比如,在一个对象的同步方法里面调用另外一个对象的同步方法,则获取了两个对象的同步锁。

8)、同步损害并发性,应该尽可能缩小同步范围。同步不但可以同步整个方法,还可以同步方法中一部分代码块。

9)、在使用同步代码块时候,应该指定在哪个对象上同步,也就是说要获取哪个对象的锁。

 

 

为何要使用同步? 

java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查), 将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他线程的调用, 从而保证了该变量的唯一性和准确性。

 

 

 

1.同步方法 

    即有synchronized关键字修饰的方法。 由于java的每个对象都有一个内置锁,当用此关键字修饰方法时, 内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。   

注: synchronized关键字也可以修饰静态方法,此时如果调用该静态方法,将会锁住整个类

 

2.同步代码块 

    即有synchronized关键字修饰的语句块。 被该关键字修饰的语句块会自动被加上内置锁,从而实现同步。

注:同步是一种高开销的操作,因此应该尽量减少同步的内容。 通常没有必要同步整个方法,使用synchronized代码块同步关键代码即可。 

 

3.使用特殊域变量(volatile)实现线程同步

    a.volatile关键字为域变量的访问提供了一种免锁机制, 

    b.使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新, 

    c.因此每次使用该域就要重新计算,而不是使用寄存器中的值 

    d.volatile不会提供任何原子操作,它也不能用来修饰final类型的变量 

 

 

4.使用重入锁实现线程同步

    在JavaSE5.0中新增了一个java.util.concurrent包来支持同步。 ReentrantLock类是可重入、互斥、实现了Lock接口的锁, 它与使用synchronized方法和快具有相同的基本行为和语义,并且扩展了其能力

 

    ReenreantLock类的常用方法有:

        ReentrantLock() : 创建一个ReentrantLock实例 

        lock() : 获得锁 

        unlock() : 释放锁 

注:ReentrantLock()还有一个可以创建公平锁的构造方法,但由于能大幅度降低程序运行效率,不推荐使用 

 

注:关于Lock对象和synchronized关键字的选择: 

   a.最好两个都不用,使用一种java.util.concurrent包提供的机制, 能够帮助用户处理所有与锁相关的代码。 

   b.如果synchronized关键字能满足用户的需求,就用synchronized,因为它能简化代码 

   c.如果需要更高级的功能,就用ReentrantLock类,此时要注意及时释放锁,否则会出现死锁,通常在finally代码释放锁 

 

 

5.使用局部变量实现线程同步 

    如果使用ThreadLocal管理变量,则每一个使用该变量的线程都获得该变量的副本, 副本之间相互独立,这样每一个线程都可以随意修改自己的变量副本,而不会对其他线程产生影响。

  

ThreadLocal 类的常用方法

    ThreadLocal() : 创建一个线程本地变量 

    get() : 返回此线程局部变量的当前线程副本中的值 

    initialValue() : 返回此线程局部变量的当前线程的"初始值" 

    set(T value) : 将此线程局部变量的当前线程副本中的值设置为value

 

注:ThreadLocal与同步机制 

  a.ThreadLocal与同步机制都是为了解决多线程中相同变量的访问冲突问题。 

  b.前者采用以"空间换时间"的方法,后者采用以"时间换空间"的方式

 

 

6.使用阻塞队列实现线程同步

    前面5种同步方式都是在底层实现的线程同步,但是我们在实际开发当中,应当尽量远离底层结构。  使用javaSE5.0版本中新增的java.util.concurrent包将有助于简化开发。  本小节主要是使用LinkedBlockingQueue<E>来实现线程的同步  LinkedBlockingQueue<E>是一个基于已连接节点的,范围任意的blocking queue。  队列是先进先出的顺序(FIFO),关于队列以后会详细讲解~ 

   

   LinkedBlockingQueue 类常用方法 

    LinkedBlockingQueue() : 创建一个容量为Integer.MAX_VALUE的LinkedBlockingQueue 

    put(E e) : 在队尾添加一个元素,如果队列满则阻塞 

    size() : 返回队列中的元素个数 

    take() : 移除并返回队头元素,如果队列空则阻塞 

 

 

注:BlockingQueue<E>定义了阻塞队列的常用方法,尤其是三种添加元素的方法,我们要多加注意,当队列满时:

  add()方法会抛出异常

  offer()方法返回false

  put()方法会阻塞

 

 

 

7.使用原子变量实现线程同步

需要使用线程同步的根本原因在于对普通变量的操作不是原子的。那么什么是原子操作呢?

原子操作就是指将读取变量值、修改变量值、保存变量值看成一个整体来操作即-这几种行为要么同时完成,要么都不完成。

在java的util.concurrent.atomic包中提供了创建了原子类型变量的工具类,使用该类可以简化线程同步。

 

其中AtomicInteger 表可以用原子方式更新int的值,可用在应用程序中(如以原子方式增加的计数器),但不能用于替换Integer;可扩展Number,允许那些处理机遇数字类的工具和实用工具进行统一访问。

 

AtomicInteger类常用方法:

AtomicInteger(int initialValue) : 创建具有给定初始值的新的AtomicInteger

addAddGet(int dalta) : 以原子方式将给定值与当前值相加

get() : 获取当前值

 

补充--原子操作主要有:

  对于引用变量和大多数原始变量(long和double除外)的读写操作;

  对于所有使用volatile修饰的变量(包括long和double)的读写操作。

]]>
【JAVA之Grizzly 介绍】 http://doc.okbase.net/gaojingsong/archive/265405.html gaojingsong 2017/9/8 8:06:42

Writing scalable server applications in the Java™ programming language has always been difficult. Before the advent of the Java New I/O API (NIO), thread management issues made it impossible for a server to scale to thousands of users. The Grizzly NIO framework has been designed to help developers to take advantage of the Java™ NIO API. Grizzly’s goal is to help developers to build scalable and robust servers using NIO as well as offering extended framework components: Web Framework (HTTP/S), WebSocket, Comet, and more!




Core Framework

Memory Management

I/O Strategies

Transports and Connections

FilterChain and Filters

Core Configuration

Port Unification

Monitoring

Best Practices

Quick Start

Samples

 

 

HTTP Components

Core HTTP Framework

HTTP Server Framework

HTTP Server Framework Extras

Comet

JAXWS

WebSockets

AJP

MAIN

 



 

核心框架

内存管理:Grizzly2.0引入了以可以在运行时(runtime)提高内存管理的子系统。该子系统包括三个主要构件:

缓冲区(Buffers)

ThreadLocal的内存池(ThreadLocal memory pools)

MemoryManager作为一个实用缓冲区和内存池工厂

I/O策略:通常我们使用一下两种方处理特定的NIO事件:在接收到的线程直接处理(Same-thread)或者交给工作线程处理(Worker-thread)。

Worker-thread IOStrategy

Same-thread IOStrategy

动态IOStrategy

Leader-follower IOStrategy

传输和连接:Transport和Connection是Grizzly2.3的核心网络API。

Transport定义了网络传输方式如TCP、UDP,包括相关资源(线程池、内存管理器等)和嵌套连接的缺省配置。

Connection在Grizzly2.3代表一个TCP或UDP的单一网络连接(很像socket)。

Transport和Connection是一对多的关系。

过滤器链和过滤器:过滤器链顾名思义就是多个过滤器组成链。每个过滤器表示一个要执行的处理单元,用于检查并(或)修改由FilterChainContext表示的一个事务的状态。

核心配置:核心框架配置的要点是Transport实例及其相关线程池。

端口统一:有时由于某些管理限制我们只能使用一个端口来发布多个服务,根据请求重定向到相应服务。Grizzly中的“端口统一”就是这个问题的解决方案。

监控:Grizzly提供了监控框架内部关键组件的功能,且允许通过自定义扩展监控组件。

 

HTTP组件

核心HTTP框架:Grizzly2.3 HTTP框架提供了服务器和客户端的编解码HTTP请求响应数据的功能。除了编解码器本身,框架还包括基本HTTP原语和简化协议相关工作的工具类。

HTTP服务器框架

简单的服务器API使Grizzly可以轻松嵌入应用程序。

类似Servlet规范的抽象:HttpHandler (Servlet), Request (HttpServletRequest), Response (HttpServletResponse)。

通过响应挂起/恢复机制提供处理长时间运行的HTTP事务的能力。

支持非阻塞IO流。

静态内容的使用文件缓存。

HTTP服务器框架扩展

Comet

JAXWS:从2.1.2版本开始Grizzly通过HTTP服务器框架支持JAX-WS web服务。

WebSockets:Grizzly实现了RFC 6455的要求,同时也支持此协议的旧版本。这对于没有实现最终草案规范的客户端很有用。

AJP:从2.1版本开始Grizzly开始支持AJP1.3。

SPDY:从2.3版本开始Grizzly支持SPDY/3。SPDY的目标是降低网页加载时间。

  • 大小: 99.7 KB
  • 大小: 361.2 KB
]]> 【java之Spray介绍】 http://doc.okbase.net/gaojingsong/archive/265404.html gaojingsong 2017/9/8 8:06:32

This is a implementation of a websocket server and client for the spray.io web toolkit. It is currently a work in progress, but it has a pretty comprehensive test suite that exercises a whole bunch of functionality. The server/client can:



 Spray是基于Akka之上的轻量级Scala库,提供对客户端与服务端REST/HTTP的支持。在使用上,大概可以将其视为Java平台下的Jersey;虽然它们的特性并不尽相同。从scala语言来看,它提供的Future与Promise可以较好地支持并发;而Akka的Actor模型无疑助推了Spray的并发处理性能。根据Spray官方网站的描述,它拥有如下的特性:

完全异步的,无阻塞的APIs

基于Actor与Future

高性能

轻量级

模块化

可测试性

 

 

Work under SSL (all the tests are done both in the clear and under SSL)

Handle fragmented messages (the server will buffer up a complete message before passing it to your frameHandler

Cut off messages which are too big (whether single-messages or fragmented)

Kill the connection when there's a protocol violation according to the websocket spec (probably doesn't account for everything at the moment)

Automatically respond to pings with pongs

Match up outgoing Pings and incoming Pongs to find round trip times

Automatically ping every client according to the autoPingInterval, using the pingGenerator to generate the body of each ping

Pass almost the entire Autobahn Test Suite

client-report.html and sever-report.html contain the Autobahn test reports for both the server and the client. The only tests currently failing are unicode strictness tests, which means the server isn't killing connections in the case of malformed unicode as strictly as it should.

  • 大小: 55.4 KB
]]> 【工作流引擎之Activiti 】 http://doc.okbase.net/gaojingsong/archive/265388.html gaojingsong 2017/9/8 8:02:18

Activiti is battle-tested Business Process Management. Organizations across the world depend on the open source platform in a huge range of demanding situations. It supports open standards with BPMN and DMN so you can create processes that suit you.

工作流(workflow)就是工作流程的计算模型,即将工作流程中的工作如何前后组织在一起的逻辑和规则在计算机中以恰当的模型进行表示并对其实施计算。它主要解决的是“使在多个参与者之间按照某种预定义的规则传递文档、信息或任务的过程自动进行,从而实现某个预期的业务目标,或者促使此目标的实现”。(我的理解就是:将部分或者全部的工作流程、逻辑让计算机帮你来处理,实现自动化)



 

Activiti的创始人也就是JBPM(也是一个优秀的BPM引擎)的创始人,从Jboss离职后开发了一个新的BPM引擎:Activiti。所以,Activiti有很多地方都有JBPM的影子。所以,据说学习过JBPM的朋友学起Activiti来非常顺手。

Activiti是一个开源的工作流引擎,它实现了BPMN 2.0规范,可以发布设计好的流程定义,并通过api进行流程调度。

Activiti 作为一个遵从 Apache 许可的工作流和业务流程管理开源平台,其核心是基于 Java 的超快速、超稳定的 BPMN2.0 流程引擎,强调流程服务的可嵌入性和可扩展性,同时更加强调面向业务人员。

Activiti 流程引擎重点关注在系统开发的易用性和轻量性上。每一项 BPM 业务功能 Activiti 流程引擎都以服务的形式提供给开发人员。通过使用这些服务,开发人员能够构建出功能丰富、轻便且高效的 BPM 应用程序。

 

关键对象

1.Deployment:流程部署对象,部署一个流程时创建。

2.ProcessDefinitions:流程定义,部署成功后自动创建。

3.ProcessInstances:流程实例,启动流程时创建。 

4.Task:任务,在Activiti中的Task仅指有角色参与的任务,即定义中的UserTask。 

5.Execution:执行计划,流程实例和流程执行中的所有节点都是Execution,如UserTask、ServiceTask等。



 

 

服务接口

1.ProcessEngine:流程引擎的抽象,通过它我们可以获得我们需要的一切服务。 

2.RepositoryService:Activiti中每一个不同版本的业务流程的定义都需要使用一些定义文件,部署文件和支持数据(例如BPMN2.0 XML文件,表单定义文件,流程定义图像文件等),这些文件都存储在Activiti内建的Repository中。RepositoryService提供了对 repository的存取服务。

3.RuntimeService:在Activiti中,每当一个流程定义被启动一次之后,都会生成一个相应的流程对象实例。RuntimeService提供了启动流程、查询流程实例、设置获取流程实例变量等功能。此外它还提供了对流程部署,流程定义和流程实例的存取服务。

4.TaskService: 在Activiti中业务流程定义中的每一个执行节点被称为一个Task,对流程中的数据存取,状态变更等操作均需要在Task中完成。TaskService提供了对用户Task 和Form相关的操作。它提供了运行时任务查询、领取、完成、删除以及变量设置等功能。 

5.IdentityService: Activiti中内置了用户以及组管理的功能,必须使用这些用户和组的信息才能获取到相应的Task。IdentityService提供了对Activiti 系统中的用户和组的管理功能。

6.ManagementService: ManagementService提供了对Activiti流程引擎的管理和维护功能,这些功能不在工作流驱动的应用程序中使用,主要用于Activiti系统的日常维护。 

7.HistoryService: HistoryService用于获取正在运行或已经完成的流程实例的信息,与RuntimeService中获取的流程信息不同,历史信息包含已经持久化存储的永久信息,并已经被针对查询优化。

  • 大小: 16.2 KB
  • 大小: 75 KB
]]> 【JAVA验证码之Kaptcha】 http://doc.okbase.net/gaojingsong/archive/265387.html gaojingsong 2017/9/8 8:02:04

Kaptcha是一个基于SimpleCaptcha的验证码开源项目。kaptcha 是一个非常实用的验证码生成工具。有了它,你可以生成各种样式的验证码,因为它是可配置的。kaptcha工作的原理是调用 com.google.code.kaptcha.servlet.KaptchaServlet,生成一个图片。同时将生成的验证码字符串放到 HttpSession中。

SimpleCaptcha is a Java library for generating CAPTCHA challenge/answer pairs. SimpleCaptcha is intended to be easy to implement and use sensible defaults, while providing easily-accesssible hooks for customization. Example implementations are provided in J2EE and Grails.

使用kaptcha可以方便的配置:

验证码的字体

验证码字体的大小

验证码字体的字体颜色

验证码内容的范围(数字,字母,中文汉字!)

验证码图片的大小,边框,边框粗细,边框颜色

验证码的干扰线(可以自己继承com.google.code.kaptcha.NoiseProducer写一个自定义的干扰线)

验证码的样式(鱼眼样式、3D、普通模糊……当然也可以继承com.google.code.kaptcha.GimpyEngine自定义样式)


配置文件详解 

<servlet>

<servlet-name>Kaptcha</servlet-name>

  <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>

  <!-- 设置是否有边框 -->

  <init-param>

   <param-name>kaptcha.border</param-name>

   <param-value>yes</param-value>

  </init-param>

  <!-- 设置边框颜色-->

  <init-param>

   <param-name>kaptcha.border.color</param-name>

   <param-value>105,179,90</param-value>

  </init-param>

  <!-- 获取中文 -->

  <init-param>

   <param-name>kaptcha.textproducer.impl</param-name>

   <param-value>org.cric.util.ChineseText</param-value>

  </init-param>

  <!-- 设置字体颜色 -->

  <init-param>

   <param-name>kaptcha.textproducer.font.color</param-name>

   <param-value>black</param-value>

  </init-param>

  <!-- 设置验证码宽度 -->

  <init-param>

   <param-name>kaptcha.image.width</param-name>

   <param-value>130</param-value>

  </init-param>

  <!-- 设置验证码高度 -->

  <init-param>

   <param-name>kaptcha.image.height</param-name>

   <param-value>44</param-value>

  </init-param>

  <!-- 设置字体大小 -->

  <init-param>

   <param-name>kaptcha.textproducer.font.size</param-name>

   <param-value>30</param-value>

  </init-param>

  <!-- 设置字体个数 -->

  <init-param>

   <param-name>kaptcha.textproducer.char.length</param-name>

   <param-value>4</param-value>

  </init-param>

  <!-- 设置字体样式 -->

  <init-param>

   <param-name>kaptcha.textproducer.font.names</param-name>

   <param-value>宋体,楷体,微软雅黑</param-value>

  </init-param>

 </servlet>

 

  • 大小: 12.4 KB
  • 大小: 9.9 KB
  • 大小: 52.5 KB
]]> 【Pushlet 介绍】 http://doc.okbase.net/gaojingsong/archive/265306.html gaojingsong 2017/8/27 9:31:10

Pushlet 是一个开源的 Comet 框架,Pushlet 使用了观察者模式:客户端发送请求,订阅感兴趣的事件;服务器端为每个客户端分配一个会话 ID 作为标记,事件源会把新产生的事件以多播的方式发送到订阅者的事件队列里。

 

 

server端向浏览器client发送通知这种通讯模式在J2EE应用中很常见,通常使用采用RMI、CORBA或者自定义TCP/IP信息的applet来实现。这些技术往往由于复杂而产生诸多不利之处:技术难以实现、存在防火墙限制(因为需要打开非HTTP的通讯端口)、需要额外的server开发和维护。并且除了刷新整个页面或者完全采用applet展示内容之外,很难找到别的方法将client端applet的状态和浏览器的页面内容集成在一起。

 

Pushlet是一种comet实现:在Servlet机制下,数据从server端的Java对象直接推送(push)到(动态)HTML页面,而无需任何Java applet或者插件的帮助。它使server端可以周期性地更新client的web页面,这与传统的request/response方式相悖。浏览器client为兼容JavaScript1.4版本以上的浏览器(如Internet Explorer、FireFox),并使用JavaScript/Dynamic HTML特性。而底层实现使用一个servlet通过Http连接到JavaScript所在的浏览器,并将数据推送到后者。有关JavaScript版本的知识请参看Mozilla开发中心提供的《JavaScript核心参考》和Stephen Chapman编写的《What Version of Javascript》。

 

这种机制是轻量级的,它使用server端的servlet连接管理、线程工具、javax.servlet API,并通过标准Java特性中Object的wait()和notify()实现的生产者/消费者机制。原则上,Pushlet框架能够运行在任何支持servlet的server上、防火墙的后面。当在client中使用JavaScript/DHTML时,Pushlet提供了通过脚本快速建立应用、使用HTML/CSS特性集成和布局新内容的便利方法。

 

 

原理

Pushlet的基本使用形式是极为简单的。后面的一些示例会说明这一点。

Pushlet基于HTTP流,这种技术常常用在多媒体视频、通讯应用中,比如QuickTime。与装载HTTP页面之后马上关闭HTTP连接的做法相反,Pushlet采用HTTP流方式将新变动的数据主动地推送到client(客户端),再此期间HTTP连接一直保持打开。有关如何在Java中实现这种Keep-alive的长连接请参看Sun提供的《HTTP Persistent Connection》和W3C的《HTTP1.1规范》。

 

 

解决方案

让我们对应用进行这样的假设:拥有一个Java web server或者Java应用server,我们试图从server发送通知给client端浏览器。这里的解决方案可以分为:“轮询(polling)”、“服务端回调(server-side callbacks)”和“消息(messaging)”三类。

 

轮询

最简单的解决方案便是“定时刷新页面”。在HTML文档的头部使用HTML META标签,页面便可以每隔N秒自动reload一次。如果在此期间server端数据发生变化,那么我们可以获得新的内容,否则将得到相同的页面。虽然方法很简单,但是如何设置刷新间隔是让人头疼的大问题。

服务器回调

因为我们是“身经百战”的Java开发老手,所以经常会用到“服务端回调”。这种方式通过RMI或者CORBA将Server端的对象传输到Java applet客户端。

 

消息(MOM)

这种解决方案采用一个作为client的applet,它使用TCP/IP或者无连接的UDP、甚至多播协议来建立与消息中间件server的通讯,然后由server推送消息给client。你可以从例如SoftWired的iBus、IBM的MQSeries、BEA的WebLogic Event这些消息产品中直接挑选,或者自己使用基于socket的 .ObjectStream定制开发消息软件。

 

讨论(MOM)

上面三种解决方案在复杂性、安全性、性能、可测量性、浏览器兼容性、防火墙限制上各有优势、劣势。最佳解决方案依赖于你的应用需求。例如,在共享白板应用中,用户需要直接与“状态”交互,那么server端回调或者消息很可能会大显身手。

但在浏览器环境下,除非完全使用applet作为整个client应用,否则把来自于server的更新信息集成到页面中并非易事。如何在applet收到回调或者消息时变更页面相关内容?一个很“痛快”而又“痛苦”的解决方案就是在回调方法中使用AppletContext.showDocument(URL)方法来刷新整个页面。

 

由于HTML代码可以直接影响页面布局,直接使用来自server的数据更改HTML部分内容不是更好吗?这是web应用的理想方案,在server上内容动态改变时,从用户到server所需的交互是最小化的。作为对上面的解决方案的补充,我开发了Pushlet这种轻量级、瘦客户端的技术,它无需applet或者插件而直接与脚本/HTML集成在一起、使用标准HTTP连接、理论上可以部署到任何支持Java servlet的server上。但这并不意味着它将替换对前面解决方案,而是在你的开发“工具箱”中添加另一种选择。作为Java构架者/开发者,你可以自行权衡、选择、决定哪种适合应用的解决方案。

]]>
【JAVA EE之基础面试题】 http://doc.okbase.net/gaojingsong/archive/265244.html gaojingsong 2017/8/14 12:42:36

永久链接: http://gaojingsong.iteye.com/blog/2386483

预览文章: 【JAVASE基础面试题】 

 

1、网络编程(Socket/DatagramSocket/ServerSocketChannel )

Socket通信的步骤

 ① 创建ServerSocket和Socket

 ② 打开连接到Socket的输入/输出流

 ③ 按照协议对Socket进行读/写操作

 ④ 关闭输入输出流、关闭Socket

服务器端:

 ① 创建ServerSocket对象,绑定监听端口

 ② 通过accept()方法监听客户端请求

 ③ 连接建立后,通过输入流读取客户端发送的请求信息

 ④ 通过输出流向客户端发送乡音信息

 ⑤ 关闭相关资源

客户端:

 ① 创建Socket对象,指明需要连接的服务器的地址和端口号

 ② 连接建立后,通过输出流想服务器端发送请求信息

 ③ 通过输入流获取服务器响应的信息

 ④ 关闭响应资源 

 

应用多线程实现服务器与多客户端之间的通信

① 服务器端创建ServerSocket,循环调用accept()等待客户端连接

② 客户端创建一个socket并请求和服务器端连接

③ 服务器端接受苦读段请求,创建socket与该客户建立专线连接

④ 建立连接的两个socket在一个单独的线程上对话

⑤ 服务器端继续等待新的连接      

 

 

DatagramSocket连接过程

服务器端实现步骤

① 创建DatagramSocket,指定端口号

② 创建DatagramPacket

③ 接受客户端发送的数据信息

④ 读取数据

客户端实现步骤

① 定义发送信息

② 创建DatagramPacket,包含将要发送的信息

③ 创建DatagramSocket

④ 发送数据

 

ServerSocketChannel 

http://gaojingsong.iteye.com/admin/blogs/2371061

http://gaojingsong.iteye.com/admin/blogs/2371060

 

2、TCP和UDP的区别

 

3、网络协议

 

4、Servlet生命周期与工作原理

http://gaojingsong.iteye.com/admin/blogs/2316060

 

5、网络七层模型与四层模型

 

6、Socket是什么?

 

7、socket的基本操作

 1、socket()函数

 2、bind()函数

 3、listen()、connect()函数

 4、accept()函数

 5、read()、write()函数等

 6、close()函数

 

 

8、TCPIP连接与断开过程(socket中TCP的三次握手建立连接详解/socket中TCP的四次握手释放连接详解网络中进程之间如何通信?)

提示:三次握手和四次断开

 

9、转发与重定向的区别

 

10、Http协议格式以及其包含的方法有哪些,以及方法之间的区别?

http://gaojingsong.iteye.com/blog/2317591

 

11、JSP的九大内置对象以及其作用域

http://gaojingsong.iteye.com/blog/2316067

 

12、常见的MVC模型

 

13、java解析XML(Dom/Sax/Dom4J/Xpull/JAXP  DocumentBuilderFactory)以及区别

DOM的基本对象有5个:Document,Node,NodeList,Element和Attr。

 

14、JNI的调用过程

 

15、文件上传与下载以及导入导出Excel

 

16、Ajax的原理以及跨域问题

 

17、使用Socket/URLConnection/HttpClient模拟Http请求/登录

http://gaojingsong.iteye.com/blog/2264395

 

18、RPC VS WebService以及其解决的是什么问题即为何使用它们

 

19、Session与Cookie的区别

 

20、闭包

 

21、反射以及为何使用反射

 

温馨提示:欢迎加群找群主索取答案(企鹅群516569942)

 

原创不易,欢迎打赏,请认准正确地址,谨防假冒



 

 


]]>
【OAUTH协议 介绍】 http://doc.okbase.net/gaojingsong/archive/265243.html gaojingsong 2017/8/14 12:42:24

OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是OAUTH的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此OAUTH是安全的。oAuth是Open Authorization的简写。

 

OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。同时,任何第三方都可以使用OAUTH认证服务,任何服务提供商都可以实现自身的OAUTH认证服务,因而OAUTH是开放的。业界提供了OAUTH的多种实现如PHP、JavaScript,Java,Ruby等各种语言开发包,大大节约了程序员的时间,因而OAUTH是简易的。互联网很多服务如Open API,很多大公司如Google,Yahoo,Microsoft等都提供了OAUTH认证服务,这些都足以说明OAUTH标准逐渐成为开放资源授权的标准。

在官方网站的首页,可以看到下面这段简介:

An open protocol to allow secure API authorization in a simple and standard method from web, mobile and desktop applications.

大概意思是说OAUTH是一种开放的协议,为桌面、手机或web应用提供了一种简单的,标准的方式去访问需要用户授权的API服务。OAUTH类似于Flickr Auth、Google's AuthSub 、Yahoo's BBAuth、 Facebook Auth等。

 

OAUTH协议特点

(1). 简单:不管是OAUTH服务提供者还是应用开发者,都很易于理解与使用;

(2). 安全:没有涉及到用户密钥等信息,更安全更灵活;

(3). 开放:任何服务提供商都可以实现OAUTH,任何软件开发商都可以使用OAUTH;

 

OAUTH原理

 

第一步:用户访问第三方网站,比如:就是你需要使用QQ进行登录的网站;

 

第二步:你点击QQ登录后,第三方网站将会连接并进行请求,比如:你点击登录后,第三方网站会跳转到QQ平台,提示你进行登录;

 

第三步:你要进行授权第三方网站对你的信息访问的一个权限,比如:当你QQ登录成功后,QQ会提示你,是否授权第三方Web访问你的用户基本信息或其他的资源信息,这时你点击授权即可;

 

第四步:授权后,第三方Web即可访问你刚才授权的资源信息,比如:你的QQ基本信息-头像、昵称、性别等。

 

相关术语

三个URL

Request Token URL: 获取未授权的Request Token服务地址;

User Authorization URL: 获取用户授权的Request Token服务地址;

Access Token URL: 用授权的Request Token换取Access Token的服务地址;


 第一步:网站向认证平台请求一个未授权的Token,这个Request Token Url是前面说的第一个Url;

 

第二步:跳转至用户授权页面,提示用户进行登录,并进行授权,返回获得已授权的Token,用到的User Authorization Url是前面说的第二个Url;

 

第三步:通过已授权的Token,向认证平台请求Access Token(数据令牌),用到的Request Access Url是前面说的第三个Url,返回后到这步整个认证流程就结束了,最后一步,是通过数据令牌等参数,调用接口获取用户信息,不完全算认证的流程。(我喜欢简洁明了,认证流程就是这样,相信通过图示及讲解都能明白,若有不明白之处请留言)

 

 

 

参数定义

OAUTH_consumer_key: 使用者的ID,OAUTH服务的直接使用者是开发者开发出来的应用。所以该参数值的获取一般是要去OAUTH服务提供商处注册一个应用,再获取该应用的OAUTH_consumer_key。

OAUTH_consumer_secret:OAUTH_consumer_key对应的密钥。

OAUTH_token:OAUTH进行到最后一步得到的一个“令牌”,通过此“令牌”请求,就可以去拥有资源的网站抓取任意有权限可以被抓取的资源。

OAUTH_token_secret:OAUTH_token对应的私钥。

OAUTH_signature_method: 请求串的签名方法,应用每次向OAUTH三个服务地址发送请求时,必须对请求进行签名。签名的方法有:HMAC-SHA1、RSA-SHA1与PLAINTEXT等三种。

OAUTH_signature: 用上面的签名方法对请求的签名。

OAUTH_timestamp: 发起请求的时间戳,其值是距1970 00:00:00 GMT的秒数,必须是大于0的整数。本次请求的时间戳必须大于或者等于上次的时间戳。

OAUTH_nonce: 随机生成的字符串,用于防止请求的重复,防止外界的非法攻击。

OAUTH_version: OAUTH的版本号。

 

 

响应代码

HTTP 400 Bad Request 请求错误

Unsupported parameter 参数错误

Unsupported signature method 签名方法错误

Missing required parameter 参数丢失

Duplicated OAUTH Protocol Parameter 参数重复

HTTP 401 Unauthorized 未授权

Invalid Consumer Key 非法key

Invalid / expired Token 失效或者非法的token

Invalid signature 签名非法

Invalid / used nonce 非法的nonce

 

 

认证流程

获取未授权的request token

请求参数:

OAUTH_consumer_key:消费方键值。

OAUTH_signature_method:消费方签署本请求所用的签名方法。

OAUTH_signature:签名,定义于签署请求 (签署请求)。

OAUTH_timestamp:定义于Nonceand Timestamp (单次值与时间戳)。

OAUTH_nonce:定义于Nonceand Timestamp (单次值与时间戳)。

OAUTH_version:可选。

额外参数:由服务提供方定义的任意额外参数

服务方返回结果,响应包含如下参数:

OAUTH_token:请求令牌

OAUTH_token_secret:令牌密钥

附加参数:由服务提供方定义的任意参数。

获取用户授权的request token

 

请求参数:

OAUTH_token:可选。在前述步骤中获得的请求令牌。服务提供方可以声明此参数为必须,也可以允许不包含在授权URL中并提示用户手工输入。

OAUTH_callback:可选。消费方可以指定一个URL,当 获取用户授权 (获取用户授权)成功后,服务提供方将重定向用户到这个URL。

附加参数:由服务提供方定义的任意参数。

服务提供方将用户引导回消费方

如果消费方在OAUTH_callback中提供了回调URL(在消费方引导用户至服务提供方 (消费方引导用户至服务提供方)中描述),则服务提供方构造一个HTTP GET请求URL,重定向用户浏览器到该URL,并包含如下参数:

OAUTH_token:被用户授权或否决的请求令牌

回调URL可以包含消费方提供的查询参数,服务提供方必须保持已有查询不变并追加OAUTH_token参数。

 

用授权的request token换取Access Token

消费方请求访问令牌参数:

OAUTH_consumer_key:消费方键值。

OAUTH_token:之前获取的请求令牌。

OAUTH_signature_method:消费方使用的签署方法。

OAUTH_signature:签署请求 (签署请求)中定义的签名。

OAUTH_timestamp:在单次值与时间戳 (单次值与时间戳)中定义。

OAUTH_nonce:在单次值与时间戳 (单次值与时间戳)中定义。

OAUTH_version:版本号,可选。

返回参数:

OAUTH_token:访问令牌。

OAUTH_token_secret:令牌密钥。

 

 

访问受保护资源

请求参数:

OAUTH_consumer_key:消费方键值。

OAUTH_token:访问令牌。

OAUTH_signature_method:消费方使用的签署方法。

OAUTH_signature:签署请求 (签署请求)中定义的签名。

OAUTH_timestamp:定义于单次值与时间戳 (单次值与时间戳).

OAUTH_nonce:定义于单次值与时间戳 (单次值与时间戳).

OAUTH_version:版本号,可选。

附加参数:服务提供方指定的附加参数。

 

 

授权流程

在弄清楚了OAUTH的术语后,我们可以对OAUTH认证授权的流程进行初步认识。其实,简单的来说,

OAUTH认证授权就三个步骤,三句话可以概括:

1. 获取未授权的Request Token

2. 获取用户授权的Request Token

3. 用授权的Request Token换取Access Token

当应用拿到Access Token后,就可以有权访问用户授权的资源了。大家可能看出来了,这三个步骤不就是对应OAUTH的三个URL服务地址嘛。一点没错,上面的三个步骤中,每个步骤分别请求一个URL,并且收到相关信息,并且拿到上步的相关信息去请求接下来的URL直到拿到Access Token。

具体每步执行信息如下:

A. 使用者(第三方软件)向OAUTH服务提供商请求未授权的Request Token。向Request Token URL发起请求,请求需要带上的参数见上图。

B. OAUTH服务提供商同意使用者的请求,并向其颁发未经用户授权的oauth_token与对应的oauth_token_secret,并返回给使用者。

C. 使用者向OAUTH服务提供商请求用户授权的Request Token。向User Authorization URL发起请求,请求带上上步拿到的未授权的token与其密钥。

D. OAUTH服务提供商将引导用户授权。该过程可能会提示用户,你想将哪些受保护的资源授权给该应用。此步可能会返回授权的Request Token也可能不返回。如Yahoo OAOAUTH就不会返回任何信息给使用者。

E. Request Token 授权后,使用者将向Access Token URL发起请求,将上步授权的Request Token换取成Access Token。请求的参数见上图,这个比第一步A多了一个参数就是Request Token。

F. OAUTH服务提供商同意使用者的请求,并向其颁发Access Token与对应的密钥,并返回给使用者。

G. 使用者以后就可以使用上步返回的Access Token访问用户授权的资源。

  • 大小: 63.9 KB
  • 大小: 26 KB
]]>