标签归档:oauth

CAS3.5.2 Server 集成 OAuth2.0 Server 详细介绍

OAuth2.0是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储用户信息,而无需将用户名和密码提供给第三方应用,CAS3.5.x(x>1)提供了OAuth2.0的支持,包括客户端和服务端,依赖cas-server-support-oauth.jar包。

基本工作过程如下:

OAuth 2.0 Authorization

Jakob Jenkov
Last update: 2014-06-15

When a client applications wants access to the resources of a resource owner, hosted on a resource server, the client application must first obtain an authorization grant. This text explains how such an application grant is obtained.

Client ID, Client Secret and Redirect URI

Before a client application can request access to resources on a resource server, the client application must first register with the authorization server associated with the resource server.

The registration is typically a one-time task. Once registered, the registration remains valid, unless the client app registration is revoked.

At registration the client application is assigned a client ID and a client secret (password) by the authorization server. The client ID and secret is unique to the client application on that authorization server. If a client application registers with multiple authorization servers (e.g. both Facebook, Twitter and Google), each authorization server will issue its own unique client ID to the client application.

Whenever the client application requests access to resources stored on that same resource server, the client application needs to authenticate itself by sending along the client ID and the client secret to the autorhization server.

During the registration the client also registers a redirect URI. This redirect URI is used when a resource owner grants authorization to the client application. When a resource owner has successfully authorized the client application via the authorization server, the resource owner is redirected back to the client application, to the redirect URI.

Authorization Grant

The authorization grant is given to a client application by the resource owner, in cooperation with the authorization server associated with the resource server.

The OAuth 2.0 specification lists four different types of authorization grants. Each type has different security characteristics. The authorization grant types are:

  • Authorization Code
  • Implicit
  • Resource Owner Password Credentials
  • Client Credentials

Each of these authorization grant types is covered in the following sections.

Authorization Code

An authorization grant using an authorization code works like this (the numbers correspond to the steps shown in the diagram below the description):

1) The resource owner (user) accesses the client application.

2) The client application tells the user to login to the client application via an authorization server (e.g. Facebook, Twitter, Google etc.).

3) To login via the authorizaion server, the user is redirected to the authorization server by the client application. The client application sends its client ID along to the authorization server, so the authorization server knows which application is trying to access the protected resources.

4) The user logs in via the authorization server. After successful login the user is asked if she wants to grant access to her resources to the client application. If the user accepts, the user is redirected back to the client application.

5) When redirected back to the client application, the authorization server sends the user to a specific redirect URI, which the client application has registered with the authorization server ahead of time. Along with the redirection, the authorization server sends an authorization code, representing the authorization.

6) When the redirect URI in the client application is accessed, the client application connects directly to the authorization server. The client application sends the authorization code along with its own client ID and and client secret.

7) If the authorization server can accept these values, the authorization server sends back an access token.

10) The client application can now use the access token to request resources from the resource server. The access token serves as both authentication of the client, resource owner (user) and authorization to access the resources.

Here is a diagram illustrating the authorization process when using authorization code to authorize a client application:

1
Authorization grant via authorization code.

Implicit

An implicit authorization grant is similar to an authorization code grant, except the access token is returned to the client application already after the user has finished the authorization. The access token is thus returned when the user agent is redirected to the redirect URI.

This of course means that the access token is accessible in the user agent, or native application participating in the implicit authorization grant. The access token is not stored securely on a web server.

Furthermore, the client application can only send its client ID to the authorization server. If the client were to send its client secret too, the client secret would have to be stored in the user agent or native application too. That would make it vulnerable to hacking.

Implicit authorization grant is mostly used in a user agent or native client application. The user agent or native application would receive the access token from the authorization server.

Here is an illustration of implicit authorization grant:

2
Implicit authorization grant.

Resource Owner Password Credentials

The resource owner password credentials authorization grant method works by giving the client application access to the resource owners credentials. For instance, a user could type his Twitter user name and password (credentials) into the client application. The client application could then use the user name and password to access resources in Twitter.

Using the resource owner password credentials requires a lot of trust in the client application. You do not want to type your credentials into an application you suspect might abuse it.

The resource owner password credentials would normally be used by user agent client applications, or native client applications.

Client Credentials

Client credential authorization is for the situations where the client application needs to access resources or call functions in the resource server, which are not related to a specific resource owner (e.g. user). For instance, obtaining a list of venues from Foursquare. This does not necessary have anything to do with a specific Foursquare user.

cas 3.5.2下载地址:https://github.com/apereo/cas/releases/tag/v3.5.2

CAS默认提供了三个服务:

/oauth2.0/authorize

需要输入GET参数:client_id和redirect_uri

/oauth2.0/accessToken

需要输入GET参数:client_idredirect_uriclient_secret和代码

/oauth2.0/profile

需要输入GET参数:access_token

关于CAS3.5.x Server版本接入oauth2.0 Server配置步骤,下面为本站素文宅www.yoodb.com大家分享一下个人总结,仅供大家参考学习使用。

1、将cas-server-support-oauth工程引入cas-server-webapp项目中,通过pom.xml文件,增加内容如下:

<dependency>
<groupId>org.jasig.cas</groupId>
<artifactId>cas-server-support-oauth</artifactId>
<version>${project.version}</version>
</dependency>

2、配置应用获得client_id和client_secret

在QQ、新浪等使用第三方登录中,通常提供页面供用户申请应用,然后提供用户client_id和client_secret,并允许用户配置回调地址,那么oauth2.0 server考虑的就是需要持久化这些配置,CAS默认在文件deployerConfigContext.xml的serviceRegistryDao中配置应用服务,注意实际使用可以将申请的应用信息存储在数据库中,具体配置如下:

<bean
id="serviceRegistryDao"
        class="org.jasig.cas.services.InMemoryServiceRegistryDaoImpl">
            <property name="registeredServices">
                <list>
                    <bean class="org.jasig.cas.services.RegexRegisteredService">
                        <property name="id" value="0" />
                        <property name="name" value="HTTP and IMAP" />
                        <property name="description" value="Allows HTTP(S) and IMAP(S) protocols" />
                        <property name="serviceId" value="^(https?|imaps?)://.*" />
                        <property name="evaluationOrder" value="10000001" />
<!-- 参数回传 -->
                        <property name="ignoreAttributes" value="true"/>
                    </bean>
                    <bean class="org.jasig.cas.services.RegisteredServiceImpl">
                    <property name="id" value="1" />
                    <property name="name" value="HTTP" />
                    <property name="description" value="oauth wrapper callback url" /><!-- oauth wrapper callback url -->
                    <property name="serviceId" value="${server.prefix}/oauth2.0/callbackAuthorize" />
                </bean>
               <bean class="org.jasig.cas.services.RegisteredServiceImpl">
                <property name="id" value="2" />
                <property name="name" value="key" />
                <property name="description" value="secret" />
                <property name="serviceId" value="http://www.yoodb.com/" />
                <property name="theme" value="Yoodb" />
              </bean>
                </list>
            </property>
        </bean>

如上述代码所示,新注册了两个bean,第一个bean不需要考虑那是默认存在的bean,如果想了解参考地址:bean http://blog.yoodb.com/yoodb/article/detail/1223,我们新增的第二个bean中,name为client_id,description为client_secret,serviceId为回调地址,theme为应用名称,下面为大家说说第一个bean的用法及其用途。

3、 Oauth client构造url获得authorization_code(ST票据)

1)cas server对/oauth2.0/authorize的url进行拦截处理,需要配置映射,在web.xml中增加配置信息如下:

<servlet-mapping>
    <servlet-name>cas</servlet-name>
    <url-pattern>/oauth2.0/*</url-pattern>
</servlet-mapping>

2)在cas-servlet.xml配置文件,增加内容如下:

<bean
      id="handlerMappingC"
      class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="mappings">
      <props>
...
...
<prop key="/oauth2.0/*">oauth20WrapperController</prop>
...
...
<props>
</bean>
<bean id="oauth20WrapperController"
    class="org.jasig.cas.support.oauth.web.OAuth20WrapperController"
    p:loginUrl="${server.prefix}/login" p:servicesManager-ref="servicesManager"
    p:ticketRegistry-ref="ticketRegistry" p:timeout="7200" />

配置完成后,我们获取授权码的链接会转向login页面,此时的service地址就是第二步时新增的bean配置的第一个bean的serviceId,通过这个默认提供的地址间接的获取到ST票据,具体请求如下:

CAS Server在浏览器中打开地址:

http://localhost:8080/cas/oauth2.0/authorize?client_id=key&redirect_uri=http://www.yoodb.com/&response_type=codea

将会跳转到地址:

http://localhost:8080/cas/login?service=http%3A%2F%2F127.0.0.1%3A8080%2Fcas%2Foauth2.0%2FcallbackAuthorize

,从而间接的获取到ST票据。认证成功之后,就会携带值为ST票据的参数跳转到callbackAuthorize页面,此时生成的ST即为授权码,其中回调地址、服务名称是通过session传递过来的,注意到浏览器地址变为如下:

http://localhost:8080/cas/oauth2.0/callbackAuthorize?ticket=ST-5-u53bEqNQz2phBhnocFsb-www.yoodb.com

默认授权码只能使用一次且有效时间为10s,可以参考http://blog.yoodb.com/yoodb/article/detail/1225文章,通过修改票据过期策略进行配置时间。

4、通过ST票据授权码获得access_token

在浏览器中输入如下地址:

http://localhost:8080/cas/oauth2.0/accessToken?client_id=key&client_secret=secret&
grant_type=authorization_code&redirect_uri=http://www.yoodb.com/&code=ST-3-KIxamZyWgOYFcoXggdfs-www.yoodb.com

返回access_token信息如下:

access_token=TGT-6-csg7B16Pc09aZ6bx9j3Y6INMzScyZFhZcOGEqpnBUvoiLJkv93-www.yoodb.com&expires=7193

5、根据access_token获取用户信息

在浏览器中输入如下地址:

http://localhost:8080/cas/oauth2.0/cas/oauth2.0/profile?access_token=TGT-4-bxgrfir4tdCJ2O1EbR6eeguc3tcdpToZeyFBv416vdvvH1g3Nk-www.yoodb.com

根据access_token等到的返回用户信息如下:

{
    "id": "000000000000000001",
    "attributes": [
        {
            "uid": "000000000000000001"
        },
        {
            "username": "mrwang"
        },
        {
            "password": "123456"
        }
    ]
}

通过上述描述CAS3.5.x Server认证成功之后生成ST,此值即为授权码,传递给应用的回调地址即可,OAuth2的实现并不是很标准,对于CAS3.5.x Server版本需要扩展org.jasig.cas.support.oauth.web.OAuth20WrapperController类来进一步完善oauth2.0协议。

本站文章除注明转载外,均由 素文宅 整理发布,欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 素文宅博客

本文标题:CAS3.5.2 Server 集成 OAuth2.0 Server 详细介绍

本文地址:https://blog.yoodb.com/yoodb/article/detail/1226

使用Springboot搭建OAuth2.0 Server

OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版。

本文对OAuth 2.0的设计思路和运行流程,做一个简明通俗的解释,主要参考材料为RFC 6749。

OAuth 简介

OAuth 是由 Blaine Cook、Chris Messina、Larry Halff 及 David Recordon 共同发起的,目的在于为 API 访问授权提供一个安全、开放的标准。

基于 OAuth 认证授权具有以下特点:

  • 安全。OAuth 与别的授权方式不同之处在于:OAuth 的授权不会使消费方(Consumer)触及到用户的帐号信息(如用户名与密码),也是是说,消费方无需使用用户的用户名与密码就可以申请获得该用户资源的授权。
  • 开放。任何消费方都可以使用 OAuth 认证服务,任何服务提供方 (Service Provider) 都可以实现自身的 OAuth 认证服务。
  • 简单。不管是消费方还是服务提供方,都很容易于理解与使用。

OAuth 的解决方案如下图所示。

图 1. OAuth Solution

图 1. OAuth Solution

如 图 1 所示 OAuth 解决方案中用户、消费方及其服务提供方之间的三角关系:当用户需要 Consumer 为其提供某种服务时,该服务涉及到需要从服务提供方那里获取该用户的保护资源。OAuth 保证:只有在用户显式授权的情况下(步骤 4),消费方才可以获取该用户的资源,并用来服务于该用户。

从宏观层次来看,OAuth 按以下方式工作:

  1. 消费方与不同的服务提供方建立了关系。
  2. 消费方共享一个密码短语或者是公钥给服务提供方,服务提供方使用该公钥来确认消费方的身份。
  3. 消费方根据服务提供方将用户重定向到登录页面。
  4. 该用户登录后告诉服务提供方该消费方访问他的保护资源是没问题的。

各个角色之间的关系,可以通过国外网站介绍了解一下, 如下

OAuth 2.0 defines the following roles of users and applications:

  • Resource Owner
  • Resource Server
  • Client Application
  • Authorization Server

These roles are illustrated in this diagram:

OAuth 2.0 roles as defined in the specification.

The resource owner is the person or application that owns the data that is to be shared. For instance, a user on Facebook or Google could be a resource owner. The resource they own is their data. The resource owner is depicted in the diagram as a person, which is probably the most common situation. The resource owner could also be an application. The OAuth 2.0 specification mentions both possibilities.

The resource server is the server hosting the resources. For instance, Facebook or Google is a resource server (or has a resource server).

The client application is the application requesting access to the resources stored on the resource server. The resources, which are owned by the resource owner. A client application could be a game requesting access to a users Facebook account.

The authorization server is the server authorizing the client app to access the resources of the resource owner. The authorization server and the resource server can be the same server, but it doesn’t have to. The OAuth 2.0 specification does not say anything about how these two servers should communicate, if they are separate. This is an internal design decision to be made by the resource server + authorization server developers.

上述内容来源:http://tutorials.jenkov.com/oauth2/roles.html

 

前提

阅读本文之前,你需要了解:

  • Spring Boot
  • Spring MVC
  • Spring Security
  • Google 浏览器插件Postman

pom.xml文件如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>

 <groupId>cn.iigrowing.study.oauth2</groupId>
 <artifactId>demo01</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>jar</packaging>

 <name>my.oauth01</name>
 <description>Demo project for Spring Boot</description>

 <parent>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-parent</artifactId>
 <version>1.5.2.RELEASE</version>
 <relativePath /> <!-- lookup parent from repository -->
 </parent>

 <properties>
 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
 <java.version>1.8</java.version>
 </properties>

 <dependencies>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter</artifactId>
 </dependency>

 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-test</artifactId>
 <scope>test</scope>
 </dependency>


 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 </dependency>

 <dependency>
 <groupId>org.springframework.security.oauth</groupId>
 <artifactId>spring-security-oauth2</artifactId>
 </dependency>

 </dependencies>

 <build>
 <plugins>
 <plugin>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-maven-plugin</artifactId>
 </plugin>
 </plugins>
 </build>


</project>

 

本项目需要添加的依赖非常简单,一共只有两个,一个是Spring Web,另一个是Spring OAuth2。

接下来是本文的核心,一共三个配置类。

SecurityConfig

package cn.iigrowing.study.oauth2.demo01;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

 @Override
 protected void configure(AuthenticationManagerBuilder auth) throws Exception {
 auth.inMemoryAuthentication()
 .withUser("user").password("123456").authorities("ROLE_USER");
 }

 @Override
 protected void configure(HttpSecurity http) throws Exception {
 http.httpBasic()
 .and().csrf().disable()
 .authorizeRequests()
 .antMatchers("/login").permitAll()
 .anyRequest().authenticated()
 .and()
 .formLogin()
 .and()
 .logout().permitAll();
 }

 @Override
 @Bean
 public AuthenticationManager authenticationManagerBean() throws Exception {
 return super.authenticationManagerBean();
 }

}

此处主要做了两件事情:

  • 配置系统用户,这里使用内存存储,添加了用户名为 user ,角色为 USER 的用户
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication()
        .withUser("user").password("123456").authorities("ROLE_USER");
}
  • 配置了默认表单登陆以及禁用了 csrf 功能,并开启了httpBasic 认证
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.httpBasic()
            .and().csrf().disable()
            .authorizeRequests()
            .antMatchers("/login").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .and()
            .logout().permitAll();
    }

AuthorizationServerConfig

package cn.iigrowing.study.oauth2.demo01;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

 @Autowired
 @Qualifier("authenticationManagerBean")
 private AuthenticationManager authenticationManager;

 @Override
 public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
 clients.inMemory()
 .withClient("client").secret("123456").scopes("read")
 .authorizedGrantTypes("authorization_code")
 .redirectUris("https://www.getpostman.com/oauth2/callback");
 }

 @Override
 public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
 endpoints.authenticationManager(authenticationManager);
 }

}

这个类是OAuth2认证的核心配置类,在这个类中,配置了OAuth Client的信息,这里有几个地方需要注意:

  • @EnableAuthorizationServer 这个注解告诉 Spring 这个应用是 OAuth2 的授权服务器
  • 必须配置 authorizedGrantTypes ,它代表了OAuth Client允许认证的类型,其值主要有:
    • authorization_code
    • password
    • client_credentials
    • implicit
    • refresh_token

    这个配置项接受的类型是个数组,允许配置多个;关于这几种类型的区别,请查看这里不再赘述

  • redirectUris 关于这个配置项,是在 OAuth2协议中,认证成功后的回调地址,因为稍后我们会使用 Postman 作为测试工具,故此处值固定为 https://www.getpostman.com/oauth2/callback ,此值同样可以配置多个

ResourceServerConfig

package cn.iigrowing.study.oauth2.demo01;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId("users-info");
}

@Override
public void configure(HttpSecurity http) throws Exception {
http
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.requestMatchers()
.antMatchers("/users/**")
.and().authorizeRequests()
.antMatchers("/users/**")
.authenticated();
}

}

这个类表明了此应用是OAuth2 的资源服务器,此处主要指定了受资源服务器保护的资源链接,我们将提供以下的资源:

@RestController
@RequestMapping("users")
public class UserController {

    @GetMapping("me")
    public Principal me(Principal principal) {
        return principal;
    }
}

注:

资源服务器可以和授权服务器是同一个,也可以分开部署

最后,我们还需添加 application.yml , 配置资源服务器的filter的顺序

server:
  port: 8043
  context-path: /uaa
logging:
  level:
    org.springframework.security: DEBUG
spring:
  application:
    name: oauth-server
security:
  oauth2:
    resource:
      serviceId: ${PREFIX:}resource
      # refer to: https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-1.5-Release-Notes#oauth-2-resource-filter
      filter-order: 3

此处的 filter-order 非常重要,因为自Spring Boot 1.5.* 之后,resource server 的 filter 的顺序默认在 basic authentication filter chain 之后,所以如果不配置此项,将会导致使用 access_token 访问 resource server 的时候返回 401 状态码。

好了,所有的开发工作已经完成,无需任何其他配置,现在我们启动服务器,并通过 Postman 访问 http://localhost:8043/uaa/users/me

因为现在还没通过认证,所以服务器将返回401 的状态码,并返回以上的错误信息。

现在我们使用 Postman 来获取access_token ,首先选择 Authorization Tab, 然后选择 TypeOAuth2.0 ,最后点击 Get New Access Token 按钮:

此时将弹出以下界面:

我们填入对应的信息:

  • Token Name: access_token
  • Auth URL: http://localhost:8043/uaa/oauth/authorize
  • Access Token URL: http://localhost:8043/uaa/oauth/token
  • Client ID: client
  • Client Secret: 123456
  • Grant Type: Authorization Code

此处配置的client相关信息对应了我们在 AuthorizationServerConfig 里面的配置,之前配置的回调地址也来自于此处的 Callback URL

接下来点击Request Token 按钮,在弹出的登陆界面中输入我们之前在 SecurityConfig 中配置的用户信息,选择Approval 并点击 Authorize 按钮,即可获取 access_token :

到这里我们就成功的获取了 token,此时再次调用 users/me Api,如无意外,将会得到以下的结果:

这个项目实现了以下的功能:

  • 使用 JWT Token进行认证
  • 多Resource Sever
  • 使用数据库存储用户以及OAuth Client信息
  • 提供相关的Rest API进行用户及 Client的管理
  • 结合了Spring Cloud

源代码:my.oauth01

小结

OAuth 协议作为一种开放的,基于用户登录的授权认证方式,目前互联网很多 Open API 都对 OAuth 提供了支持,这包括 Google, Yahoo,Twitter 等。本文以 Google 为例子,介绍了 Java 桌面程序如何开发 OAuth 认证应用。在开发桌面应用访问 Web 资源这样一类程序时,一般通行的步骤是:使用 OAuth 做认证,然后使用获得的 OAuth Access Token,通过 REST API 访问用户在服务提供方的资源。

事实上,目前 OAuth 正通过许多实现(包括针对 Java、C#、Objective-C、Perl、PHP 及 Ruby 语言的实现)获得巨大的动力。大部分实现都由 OAuth 项目维护并放在 Google 代码库 (http://oauth.googlecode.com/svn/) 上。开发者可以利用这些 OAuth 类库编写自己需要的 OAuth 应用。

搭建基于OAuth2和SSO的开放平台

开放平台介绍

什么是开放平台

开放平台在百科中的定义:
开放平台(Open Platform) 在软件行业和网络中,开放平台是指软件系统通过公开其应用程序编程接口(API)或函数(function)来使外部的程序可以增加该软件系统的功能或使用该软件系统的资源,而不需要更改该软件系统的源代码。

通俗或者说应景点的说法,开放平台,就是互联网企业,将其内部的资源(一般是数据),比如用户数据,平台业务数据,以技术的手段(一般是RESTFul接口API),开放给受控的第三方合作伙伴,活公司内部的其它一些产品,形成一个安全受控的资源暴露平台。

为什么要搭建开放平台

搭建开放平台的意义,一般在于:
1.搭建基于API的生态体系
2.利用开放平台,搭建基于计费的API数据平台
3.为APP端提供统一接口管控平台,类似于网关的概念
4.为第三方合作伙伴的业务对接提供授信可控的技术对接平台

开放平台体系结构图

open

开放平台核心模块

一个典型的开放平台,至少包含以下几个核心模块:
1.平台门户
平台门户负责向第三方展示用于进行业务及技术集成的管理界面,至少包含以下几个功能:
1.服务商入住(第三方合作伙伴入住)
2.应用配置(第三方应用管理)
3.权限申请(一般包括接口权限和字段权限)
4.运维中心(开放平台当前服务器、接口状态,服务商接口告警等)
5.帮助中心(入住流程说明,快速接入说明,API文档等)

2.鉴权服务
鉴权服务负责整个平台的安全性
1.接口调用鉴权(第三方合作伙伴是否有权限调用某接口)
2.用户授权管理(用户对某个第三方应用获取改用户信息的权限管理)
3.用户鉴权(平台用户的鉴权)
4.应用鉴权(第三方合作伙伴的应用是否有权调用该平台)

3.开放接口
开放接口用于将平台数据暴露给合作伙伴
1.平台用户接口(用于获取公司APP生态链中的用户信息)
2.平台数据接口(平台中的一些开放数据)
3.其它业务接口(平台开放的一些业务数据)

4.运营系统
运营系统是整个平台的后台业务管理系统,负责对第三方合作伙伴提出的各种申请进行审核操作,对当前应用的操作进行审计工作,对当前业务健康度进行监控等
1.服务商管理(对第三方合作伙伴的资质进行审核、操作)
2.应用管理(对第三方应用进行审核、上下线管理)
3.权限管理(对合作伙伴申请的资源进行审核、操作)
4.统计分析(监控平台当前运行状态,统计平台业务数据)

OAuth2介绍

什么是OAuth2

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

简单来说:OAuth2协议,定义了一套用户、第三方服务和存储着用户数据的平台之间的交互规则,可以使得用户无需将自己的用户名和密码暴露给第三方,即可使第三方应用获取用户在该平台上的数据,最常见的场景便是现在互联网上的各种使用XXX账号登录。

OAuth2协议中角色介绍

OAuth2协议中,共有四个参与方(角色):
1.resource owner:资源拥有者
即用户
2.resource server:资源服务器
即存储用户数据的服务器,一般对外都以RESTFul API的形式暴露用户数据,client使用access token访问resource server申请被保护起来的用户数据
3.client:客户端
即第三方应用
4.authorization server:授权服务器
用来鉴权第三方应用合法性,并对用户登录、是否授权第三方应用获取数据进行响应,并根据用户操作,想第三应用颁发用户token或者告知授权失败

OAuth2常用协议介绍

OAUTH2标准业务协议,如下图所示
oauth
A.第三方应用向用户请求授权,希望获取用户数据
B.用户同意授权
C.第三方应用拿着用户授权,向平台索要用户access token
D.平台校验第三应用合法性及用户授权真实性后,向平台发放用户access token
E.第三方应用拿着用户access token向平台索要用户数据
F.平台在校验用户access token真实性后,返回用户数据

 

各个角色之间的关系,可以通过国外网站介绍了解一下, 如下

OAuth 2.0 defines the following roles of users and applications:

  • Resource Owner
  • Resource Server
  • Client Application
  • Authorization Server

These roles are illustrated in this diagram:

OAuth 2.0 roles as defined in the specification.

The resource owner is the person or application that owns the data that is to be shared. For instance, a user on Facebook or Google could be a resource owner. The resource they own is their data. The resource owner is depicted in the diagram as a person, which is probably the most common situation. The resource owner could also be an application. The OAuth 2.0 specification mentions both possibilities.

The resource server is the server hosting the resources. For instance, Facebook or Google is a resource server (or has a resource server).

The client application is the application requesting access to the resources stored on the resource server. The resources, which are owned by the resource owner. A client application could be a game requesting access to a users Facebook account.

The authorization server is the server authorizing the client app to access the resources of the resource owner. The authorization server and the resource server can be the same server, but it doesn’t have to. The OAuth 2.0 specification does not say anything about how these two servers should communicate, if they are separate. This is an internal design decision to be made by the resource server + authorization server developers.

上述内容来源:http://tutorials.jenkov.com/oauth2/roles.html

OAuth2使用场景介绍

目前,OAuth2协议使用最多的场景还是用以给第三方应用获取用户信息,业务流程如下图所示
case
1.在浏览器中,用户点击第三方应用按钮,由第三方应用发起请求,向平台发起授权请求。
2.平台在接收到第三方应用请求后,浏览器跳转用户登录界面,请求用户进行登录。
3.用户在平台登录界面输入用户名、密码进行登录
4.平台判断用户合法性,校验失败,在浏览器中提示错误原因
5.平台判断用户是否需要对该第三方应用进行授权。(不需要授权的情况有两种:a.平台信任该第三方应用,如公司内部应用,无需用户进行授权,默认给予用户数据。b.该用户之前已经给该应用授予过权限,并且仍在有效期内)
6.如需授权,平台跳转浏览器界面至授权界面,告知用户将授予哪个第三方哪些数据权限
7.用户授权后,将用户授权码回调给第三方url
8.第三方在获取用户授权码后,带着用户授权码访问平台鉴权接口,请求用户token
9.平台在收到第三方请求后,校验授权码真实性,并返回用户token
10.第三方使用用户token向平台请求用户接口
11.平台接口判断用户token真实性,并向第三方返回用户数据

OAuth2核心功能说明

1.应用注册
应用注册后,OAuth2会下发应用app_id和app_secret,用以标记该应用的唯一性,并且这两个参数将贯穿整个OAuth协议,用以对应用合法性进行校验。同时,应用需要提供redirect_uri,用以和平台进行异步交互,获取用户令牌及错误信息。
2.授权/鉴权中心
a.对用户的应户名、密码进行鉴权
b.对第三方应用的app_id,app_secret进行鉴权
c.展示授权界面,并对用户对第三方应用的授权操作进行响应
d.对用户授权码及用户token的真实性进行鉴权
3.token管理
a.创建token、刷新token
b.查询token详细数据
c.校验token时效性

OAuth2体系结构

case

开放平台集成OAuth2体系

1.平台门户:
门户应用入住界面,需要集成OAuth2应用创建接口,录入第三方回调地址,并回显app_id和app_secret参数
2.鉴权服务:
鉴权服务需集成OAuth2的authorize及token接口,用以提供用户授权及code/token鉴权功能
3.开放接口:
开放接口需集成OAuth2的resource server角色,对用户数据进行安全管理,对第三方应用发起的请求做出响应,并对token进行真实性校验
4.运营系统:
运营系统需提供对当前OAuth2应用的管理功能,用户授权列表管理,用户token管理等OAuth2协议相关管理功能。

另外, oauth2.0 有很多类型, 如下

OAuth 2.0 Client Types

Jakob Jenkov
Last update: 2014-06-15

The OAuth 2.0 client role is subdivided into a set of client types and profiles. This text will explain these types and profiles.

The OAuth 2.0 specification defines two types of clients:

  • Confidential
  • Public

A confidential client is an application that is capable of keeping a client password confidential to the world. This client password is assigned to the client app by the authorization server. This password is used to identify the client to the authorization server, to avoid fraud. An example of a confidential client could be a web app, where no one but the administrator can get access to the server, and see the client password.

A public client is an application that is not capable of keeping a client password confidential. For instance, a mobile phone application or a desktop application that has the client password embedded inside it. Such an application could get cracked, and this could reveal the password. The same is true for a JavaScript application running in the users browser. The user could use a JavaScript debugger to look into the application, and see the client password.

Client Profiles

The OAuth 2.0 specification also mentions a set of client profiles. These profiles are concrete types of applications, that can be either confidential or public. The profiles are:

  • Web Application
  • User Agent
  • Native

Web Application

A web application is an application running on a web server. In reality, a web application typically consists of both a browser part and a server part. If a web application needs access to a resource server (e.g. to Facebook user accounts), then the client password could be stored on the server. The password would thus be confidential.

Here is an illustration of a confidential client web application:

Confidential client: Web Application.

User Agent Application

A user agent application is for instance a JavaScript application running in a browser. The browser is the user agent. A user agent application may be stored on a web server, but the application is only running in the user agent once downloaded. An example could be a little JavaScript game that only runs in the browser.

Here is an illustration of a client user agent application:

Public client: User Agent Application.

Native Application

A native application is for instance a desktop application or a mobile phone application. Native applications are typically installed on the users computer or device (phone, tablet etc.). Thus, the client password will be stored on the users computer or device too.

Here is an illustration of a client native application:

Public client: Native Application.

 

Hybrid Applications

Some applications are hybrids of these profiles. For instance, a native application can have a server part too, that does part of the work (e.g. store data). The OAuth 2.0 specification says nothing about such hybrids. However, in most cases a hybrid will be able to use the authentication models of one of these profiles.

上述资料内容来源: http://tutorials.jenkov.com/oauth2/client-types.html

SSO介绍

什么是SSO

百科:SSO英文全称Single Sign On,单点登录。SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。它包括可以将这次主要的登录映射到其他应用中用于同一个用户的登录的机制。它是目前比较流行的企业业务整合的解决方案之一。

简单来说,SSO出现的目的在于解决同一产品体系中,多应用共享用户session的需求。SSO通过将用户登录信息映射到浏览器cookie中,解决其它应用免登获取用户session的问题。

为什么需要SSO

开放平台业务本身不需要SSO,但是如果平台的普通用户也可以在申请后成为一个应用开发者,那么就需要将平台加入到公司的整体账号体系中去,另外,对于企业级场景来说,一般都会有SSO系统,充当统一的账号校验入口。

CAS协议中概念介绍

SSO单点登录只是一个方案,而目前市面上最流行的单端登录系统是由耶鲁大学开发的CAS系统,而由其实现的CAS协议,也成为目前SSO协议中的既定协议,下文中的单点登录协议及结构,均为CAS中的体现结构
CAS协议中有以下几个概念:
1.CAS Client:需要集成单点登录的应用,称为单点登录客户端
2.CAS Server:单点登录服务器,用户登录鉴权、凭证下发及校验等操作
3.TGT:ticker granting ticket,用户凭证票据,用以标记用户凭证,用户在单点登录系统中登录一次后,再其有效期内,TGT即代表用户凭证,用户在其它client中无需再进行二次登录操作,即可共享单点登录系统中的已登录用户信息
4.ST:service ticket,服务票据,服务可以理解为客户端应用的一个业务模块,体现为客户端回调url,CAS用以进行服务权限校验,即CAS可以对接入的客户端进行管控
5.TGC:ticket granting cookie,存储用户票据的cookie,即用户登录凭证最终映射的cookies

CAS核心协议介绍

case
1.用户在浏览器中访问应用
2.应用发现需要索要用户信息,跳转至SSO服务器
3.SSO服务器向用户展示登录界面,用户进行登录操作,SSO服务器进行用户校验后,映射出TGC
4.SSO服务器向回调应用服务url,返回ST
5.应用去SSO服务器校验ST权限及合法性
6.SSO服务器校验成功后,返回用户信息

CAS基本流程介绍

以下为基本的CAS协议流程,图一为初次登录时的流程,图二为已进行过一次登录后的流程
case
case

代码及示例

spring提供了整套的开源包,用以搭建OAUTH2+SSO的体系:
1.spring-oauth2:用以实现OAuth2协议,提供了上述所有四个角色提供的功能
2.spring-cas:用以实现和cas的集成,将OAuth2的登录、登出功能委托给CAS处理,并提供了统一的回调机制及凭证校验机制
3.CAS,耶鲁大学官方提供的SSO开源实现,本文的单点登录协议即按照CAS进行的说明

本文还提供了基于GO语言实现的简单OAuth2+SSO功能,详见github:

https://github.com/janwenjohn/go-oauth2-sso

原创文章,转载或摘录请说明文章来源:http://heartlifes.com

-----

下面是一个很好的 关于cas的 文章再录如下:

对的,PORTAL里一定含有SSO,在此先提一下。

下面是一些著名的调查公司显示的统计数据:

  • 用户每天平均16分钟花在身份验证任务上 - 资料来源:IDS
  • 频繁的IT用户平均有21个密码 - 资料来源:NTA Monitor Password Survey
  • 49%的人写下了其密码,而67%的人很少改变它们
  • 每79秒出现一起身份被窃事件 - 资料来源:National Small Business Travel Assoc
  • 全球欺骗损失每年约12B - 资料来源:Comm Fraud Control Assoc

使用“单点登录”整合后,只需要登录一次就可以进入多个系统,而不需要重新登录,这不仅仅带来了更好的用户体验,更重要的是降低了安全的风险和管理的消耗。

请看下面的统计数据:

  • 提高IT效率:对于每1000个受管用户,每用户可节省$70K
  • 帮助台呼叫减少至少1/3,对于10K员工的公司,每年可以节省每用户$75,或者合计$648K
  • 生产力提高:每个新员工可节省$1K,每个老员工可节省$350 - 资料来源:Giga
  • ROI回报:7.5到13个月 - 资料来源:Gartner

另外,使用“单点登录”还是SOA时代的需求之一。在面向服务的架构中,服务和服务之间,程序和程序之间的通讯大量存在,服务之间的安全认证是SOA应用的难点之一,应此建立“单点登录”的系统体系能够大大简化SOA的安全问题,提高服务之间的合作效率。

以下是一个标准的企业内通过SSO来集成各个系统间的认证与权限的模型图

好了,以上基本知识普及完毕开始我们的SSO实现。

CAS SSO

SSO实现有很多产品,我们今天选用的这个是耶鲁大学发明的CAS SSO服务器。这个CAS SSO是目前我看到过的功能较全的,使用也是最简单的配置式SSO服务器,它基于SPRING的原理,因此这个配置文件我们看起来因当是相当的熟悉的。

它分为Server版和Client版2个模块,同时它对于一些其它功能特性如:数据库、LDAP协议(就是WINDOWS AD域使用的协议)、安全等还提供了一系列的插件。因此,在本例中,我使用的是:

请严格按照我的版本号进行试验。

什么叫Server端 ,什么叫Client端?

看上图,假设我们有3个War包。
  • 一个叫cas-server.war,它放在tomcat里;
  • 一个叫cas-sample-site1.war,它放在jboss里;
  • 一个叫cas-sample-site2.war,它放在jboss里;
那么位于tomcat里的cas-server.war,它就是我们的CAS的Server端,位于jboss里的两个war就是我们CAS的client端。
SSO中的Server端与Client端概念搞清后,我们现在就开始布署吧。

布署cas-server

先说一下我们的环境:
版本号 web端口
tomcat69090
jboss78080
我们把Server端解压得到以下这样的一个文件夹

它里面含了一堆的东西,关键在于以下这个文件夹

进入该文件夹,找到这样一个war包。

把这个war包解压后重命名成cas-server.war,放于tomcat的webapp目录中去,启动tomcat一切无误后即可。

然后我们打开一个ie,输入http://localhost:9090/cas-server会得到以下这个界面,那就说明你的cas sso已经安装成功了。

配置CAS SERVER

添加依赖包

在本例中我们将使用Oracle数据库中自建一个用户表来管理我们的用户名和密码,因此:

  1. 将oracle的ojdbc6.jar放入tomcat的lib目录内D:\tomcat\lib
  2. 将cas-server-3.5.2-release\cas-server-3.5.2\modules下的这几个文件拷入tomcat\webapp\cas-server\web-inf\lib目录内

修改配置文件

CAS SSO的好处在于它的配置文件是完全spring的,你只要懂spring就可以非常容易的在里面去添加修改自己的一些功能,我们在第一天的教程中为了尽量简单,我们只需要改动一个文件,它就是:

tomcat\webapps\cas-server\WEB-INF目录下的

deployerConfigContext.xml文件

我们用纯文件编辑器打开它,找到下面这行:<bean  class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" />
把它注释掉

<!-- 
<bean class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" /> 
-->  
然后再在它下面添加如下内容
<!-- 
   <bean class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" /> 
-->  
<bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">  
      <property name="dataSource" ref="dataSource" ></property>  
      <property name="sql" value="select password from sys_user where user_id=?" ></property>  
</bean>

好,这边我们看到了一个dataSource对吧,EASY,来。。。

<!-- 
          <bean class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" /> 
-->  
          <bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">  
            <property name="dataSource" ref="dataSource" ></property>  
            <property name="sql" value="select password from sys_user where user_id=?" ></property>  
          </bean>  
    </list>  
</property>  
</bean>  
  
<bean id="dataSource"  
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
    <property name="driverClassName" value="oracle.jdbc.OracleDriver" />  
    <property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl" />  
    <property name="username" value="ymk" />  
    <property name="password" value="password_1" />  
</bean>

注意我加的这个dataSource的bean和刚才那段配置代码之间的位置对应关系哦,别胡乱搞一个回车就乱加一行哦。

全加完了,怎么样啦?完成了吗?

还没,CAS SSO严格意义上来说需要J2EE APP SERVER里实现HTTPSSSL的双向认证模式才能正常使用,但是我们因为这个是教程,因此不想搞了太麻烦,我们可以在“不使用HTTPS认证”的情况下也可以使用CAS SSO。

为此,我们要关闭CAS SSO的HTTPS认证模式,编辑:

tomcat\webapps\cas-server\WEB-INF\spring-configuration目录下的

ticketGrantingTicketCookieGenerator.xml文件

找到下面这行

  1. <bean id="ticketGrantingTicketCookieGenerator" class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator"
  2.     p:cookieSecure="true"
  3.     p:cookieMaxAge="-1"
  4.     p:cookieName="CASTGC"
  5.     p:cookiePath="/cas" />
  6. </beans>

把这边的p:cookieSecure从true改为false即可。

然后我们在oracle中建一个用户表吧,建表语句如下:

  1. CREATE TABLE SYS_USER
  2. (
  3.     "USER_ID" VARCHAR2(16),
  4.     "PASSWORD" VARCHAR2(8),
  5.      CONSTRAINT "PK_SYS_USER" PRIMARY KEY ("USER_ID")
  6. );

该表中含有一条记录:

这就是我们的用于测试的单点登录的用户名和密码了,很简单吧?

全部保存后,重启tomcat,一切无误,然后我们打开一个ie,输入http://localhost:9090/cas-server会得到以下这个界面,那就说明你的cas sso已经安装成功了。

我们在用户名中输入sso, 在密码一栏中输入aaaaaa,然后看到下面这个界面,即代表我们的cas server和我们的数据库已经完全连上了。

如果我们不按照sys_user表中的用户名和密码就随意输入用户名和密码,那我们便会得到这样的结果:

将不同的工程连接上cas server以实现单点登录

按照这个图,我们将会有2个不同的war包

  • 一个叫cas-sample-site1.war,它放在jboss里;
  • 一个叫cas-sample-site2.war,它放在jboss里;

我们在我们的eclipse里创建两个这样的war工程即可,这是非常简单的事,这2个工程都含有一个index.jsp文件。

cas-sample-site1

在它的index.jsp文件中含有如下内容:

  1. <%@ page language="java" contentType="text/html; charset=utf-8"
  2.     pageEncoding="utf-8"%>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  4. <html>
  5. <head>
  6. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  7. <title>cas sample site1</title>
  8. </head>
  9. <body>
  10. <h1>cas sample site1</h1>
  11. <a href="http://localhost:8080/cas-sample-site2/index.jsp">cas-sample-site2</a>
  12. </br>
  13. <a href="http://localhost:9090/cas-server/logout">退出</a>
  14. </body>
  15. </html>

cas-sample-site2

在它的index.jsp文件中含有如下内容:

  1. <%@ page language="java" contentType="text/html; charset=utf-8"
  2.     pageEncoding="utf-8"%>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  4. <html>
  5. <head>
  6. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  7. <title>cas sample site2</title>
  8. </head>
  9. <body>
  10. <h1>cas sample site2</h1>
  11. <a href="http://localhost:8080/cas-sample-site1/index.jsp">cas-sample-site1</a>
  12. </br>
  13. <a href="http://localhost:9090/cas-server/logout">退出</a>
  14. </body>
  15. </html>

这两个war工程都有一个lib目录,确保它们的lib目录里都有这样几个jar

look, 注意要有cas-client-core-3.2.1.jar哦,它来自于:cas-client-3.2.1-release\cas-client-3.2.1\modulescas-client-3.2.1-release.zip解压出来的内容。

 

这两个工程的web.xml可以说是完全一模一样,我们来看:

<?xml version="1.0" encoding="UTF-8"?>  
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">  
  <display-name>cas-sample-site2</display-name>  
  <welcome-file-list>  
    <welcome-file>index.jsp</welcome-file>  
    <welcome-file>index.html</welcome-file>  
    <welcome-file>index.htm</welcome-file>      
    <welcome-file>default.html</welcome-file>  
    <welcome-file>default.htm</welcome-file>  
    <welcome-file>default.jsp</welcome-file>  
  </welcome-file-list>  
   <listener>  
        <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>  
  </listener>  
      
  <filter>  
        <filter-name>CAS Single Sign Out Filter</filter-name>  
        <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>  
  </filter>  
  <filter-mapping>  
        <filter-name>CAS Single Sign Out Filter</filter-name>  
        <url-pattern>*</url-pattern>  
  </filter-mapping>  
  
  <filter>  
        <filter-name>CAS Validation Filter</filter-name>  
        <filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>  
        <init-param>  
            <param-name>casServerUrlPrefix</param-name>  
            <param-value>http://localhost:9090/cas-server</param-value>  
        </init-param>  
        <init-param>  
            <param-name>serverName</param-name>  
            <param-value>http://localhost:8080</param-value>  
        </init-param>  
        <init-param>  
            <param-name>useSession</param-name>  
            <param-value>true</param-value>  
        </init-param>  
        <init-param>  
            <param-name>redirectAfterValidation</param-name>  
            <param-value>true</param-value>  
        </init-param>  
  </filter>  
  <filter-mapping>  
        <filter-name>CAS Validation Filter</filter-name>  
        <url-pattern>*</url-pattern>  
  </filter-mapping>  
  
  <filter>  
        <filter-name>CAS Filter</filter-name>  
        <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>  
        <init-param>  
            <param-name>casServerLoginUrl</param-name>  
            <param-value>http://localhost:9090/cas-server/login</param-value>  
        </init-param>  
        <init-param>  
            <param-name>serverName</param-name>  
            <param-value>http://localhost:8080</param-value>  
        </init-param>  
  </filter>  
  <filter-mapping>  
        <filter-name>CAS Filter</filter-name>  
        <url-pattern>*</url-pattern>  
  </filter-mapping>  
  
  <filter>  
        <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>  
        <filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>  
  </filter>  
  <filter-mapping>  
        <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>  
        <url-pattern>*</url-pattern>  
  </filter-mapping>  
</web-app>

看到了没有,有这么一堆的listener和filter,而且它们一个不能漏,并且它们的顺序也是绝对不能够错的,一定要按照下面这个从上至下的顺序:

org.jasig.cas.client.session.SingleSignOutHttpSessionListener
org.jasig.cas.client.session.SingleSignOutFilter
org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter
org.jasig.cas.client.authentication.AuthenticationFilter
org.jasig.cas.client.util.HttpServletRequestWrapperFilter
漏了一个,或者顺序错了,你将会发生下列情况:

  1. 可以正常登录,无法统一注销,即然是单点登录,那么我在任意一个站点上点“注销“是不是也因该是统一注销啊?
  2. 可以登录,可以统一注销,但是拿不到cas-server上登录的用户的user session,如果我们是两个系统,那么这两个系统是不是都有web sesssion?较常用的就是user session,那么如果你的顺序配错了,或者是你漏配了一个,你是得不到cas-server上传过来的用户的一些登录信息的,这个很糟糕,这将会为我们后面的编程开发带来烦恼
  3. 不能登录
至于为什么会得到这样的一些结果?
嘿嘿!
我们在后面的课程中会来分析cas 单点登录的源码(这个过程一点不变态,很简单的,一说就通,跟着我的教程一步步走不难的),在深入源码中后你就可以看出为什么这几个东西它们有严格意义上的顺序的关系了。
在这个web.xml文件里我们可以看到有两处出现了下面的这样的东西:
<init-param>  
        <param-name>casServerUrlPrefix</param-name>  
        <param-value>http://localhost:9090/cas-server</param-value>  
</init-param>  
<init-param>  
        <param-name>serverName</param-name>  
        <param-value>http://localhost:8080</param-value>  
</init-param>

记住,上面的那行代表我们的cas server的服务器所在的地址,当用户用上面的cas-server的登录界面登录成功后,cas server 会自动跳回用户在ie地址里输入的子系统地址的首页。

如:我们先输入http://localhost:8080/cas-sample-site1,此时系统会先跳到http://localhost:9090/cas-server/login的画面要求用户先去做一次登录。

那么cas server它是怎么知道子系统地址的首页位于哪个地址(哪台服务器上)的呢,那么你要”注册“这个地址给cas server。

因此,第二行就是我们的具体的子系统的首页所在的地址。

这样的地方在我们的web.xml文件中一共出现了两处:

  • 一处位于org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter
  • 一处位于org.jasig.cas.client.authentication.AuthenticationFilter
这2处如果没配好,你会遇到下列问题:
  • 登录后无法正常跳回子系统的首页
  • 无法正常退出
  • 无法做系统间切换时的跳转
因此一定要注意啦!!!

我们把两个工程通过ECLIPSE布署在JBOSS7上,然后运行起来吧。

别忘了启动我们的Tomcat里的cas server哦。

全部启动完毕后我们在IE浏览器里输入:http://localhost:8080/cas-sample-site1 

此时浏览器显示如下画面

我们在cas server的登录画面输入我们数据库表sys_user中的相应的用户名与密码后,再来看此时的浏览器它会跑到哪儿去?

点击cas-sample-site2这个链接呢?

然后点击“退出”这个链接

此时我们再在浏览器里输入:http://localhost:8080/cas-sample-site2--有时浏览器有缓存,它还是会显示cas-sample-site2的首页,这时你可以点一下F5或者是刷新按钮(这个可以通过代码来避免jsp或者是html页中使用缓存来做到)

look!

由于是统一注销,因此一旦注销,两个WEB都无法访问了,必须要求“统一登录一下”,于是我们再次输入用户名和密码

来源: https://blog.csdn.net/u012891504/article/details/52472818

一张图搞定OAuth2.0

1、引言

本篇文章是介绍OAuth2.0中最经典最常用的一种授权模式:授权码模式

非常简单的一件事情,网上一堆神乎其神的讲解,让我不得不写一篇文章来终结它们。

一项新的技术,无非就是了解它是什么为什么怎么用。至于为什么,本篇文章不做重点探讨,网上会有各种文章举各种什么丢钥匙、发船票的例子供你去阅读,个人认为还是有些哗众取宠,没有聊到本质。

那我们就重点聊聊OAuth2.0是什么怎么用。但首先在读本文之前,你要先对OAuth2.0有一定的了解,建议先读一下阮一峰的oauth2.0文章,直接看“授权码模式”即可,带着疑问再来读本文效果更好。

http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html

2、OAuth2.0是什么

OAuth2.0是什么——豆瓣和QQ的故事

OAuth简单说就是一种授权的协议,只要授权方和被授权方遵守这个协议去写代码提供服务,那双方就是实现了OAuth模式。

举个例子,你想登录豆瓣去看看电影评论,但你丫的从来没注册过豆瓣账号,又不想新注册一个再使用豆瓣,怎么办呢?不用担心,豆瓣已经为你这种懒人做了准备,用你的qq号可以授权给豆瓣进行登录,请看。

第一步:在豆瓣官网点击用qq登录

第二步:跳转到qq登录页面输入用户名密码,然后点授权并登录

第三步:跳回到豆瓣页面,成功登录

这几秒钟之内发生的事情,在无知的用户视角看来,就是在豆瓣官网上输了个qq号和密码就登录成功了。在一些细心的用户视角看来,页面经历了从豆瓣到qq,再从qq到豆瓣的两次页面跳转。但作为一群专业的程序员,我们还应该从上帝视角来看这个过程。

OAuth2.0是什么——上帝视角

简单来说,上述例子中的豆瓣就是客户端,QQ就是认证服务器,OAuth2.0就是客户端和认证服务器之间由于相互不信任而产生的一个授权协议。呵呵,要是相互信任那QQ直接把自己数据库给豆瓣好了,你直接在豆瓣输入qq账号密码查下数据库验证就登陆呗,还跳来跳去的多麻烦。

先上一张图,该图描绘了只几秒钟发生的所有事情用上帝视角来看的流程

就这这张图,来说一下上述例子中的三个步骤在图中的表现。所用到的请求路径名称都是虚构的,所附带的请求参数忽略了一些非重点的。

如想了解每次的请求和响应的标准齐全的参数,还是去读那篇阮一峰的文章。http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html

第一步:在豆瓣官网点击用qq登录

当你点击用qq登录的小图标时,实际上是向豆瓣的服务器发起了一个 http://www.douban.com/leadToAuthorize 的请求,豆瓣服务器会响应一个重定向地址,指向qq授权登录

浏览器接到重定向地址 http://www.qq.com/authorize?callback=www.douban.com/callback ,再次访问。并注意到这次访问带了一个参数是callback,以便qq那边授权成功再次让浏览器发起这个callback请求。不然qq怎么知道你让我授权后要返回那个页面啊,每天让我授权的像豆瓣这样的网站这么多。

至于访问这个地址之后,qq那边做出怎样的回应,就是第二步的事情了。总之第一步即对应了图中的这些部分。

第二步:跳转到qq登录页面输入用户名密码,然后点授权并登录

上一步中浏览器接到重定向地址并访问 http://www.qq.com/authorize?callback=www.douban.com/callback

qq的服务器接受到了豆瓣访问的authorize,在次例中所给出的回应是跳转到qq的登录页面,用户输入账号密码点击授权并登录按钮后,一定还会访问qq服务器中校验用户名密码的方法,若校验成功,该方法会响应浏览器一个重定向地址,并附上一个code(授权码)。由于豆瓣只关心像qq发起authorize请求后会返回一个code,并不关心qq是如何校验用户的,并且这个过程每个授权服务器可能会做些个性化的处理,只要最终的结果是返回给浏览器一个重定向并附上code即可,所以这个过程在图中并没有详细展开。现把展开图画给大家。

第三步:跳回到豆瓣页面,成功登录

这一步背后的过程其实是最繁琐的,但对于用户来说是完全感知不到的。用户在QQ登录页面点击授权登陆后,就直接跳转到豆瓣首页了,但其实经历了很多隐藏的过程。

首先接上一步,QQ服务器在判断登录成功后,使页面重定向到之前豆瓣发来的callback并附上code授权码,即 callback=www.douban.com/callback

页面接到重定向,发起 http://www.douban.com/callback 请求

豆瓣服务器收到请求后,做了两件再次与QQ沟通的事,即模拟浏览器发起了两次请求。一个是用拿到的code去换token,另一个就是用拿到的token换取用户信息。最后将用户信息储存起来,返回给浏览器其首页的视图。到此OAuth2.0授权结束。

3、OAuth2.0怎么写

了解了上述过程后,代码自然就不难写了,起码框架是可以写出来的。我在github上分享了一个我自己模拟的简单的不能再简单的oauth2.0,大家可以参考一下,仅仅用于了解oauth的过程,可别用于公司哦,不然老板得开除你。

github地址:https://github.com/cc8848/dataU-OAuth

dataU-OAuth-master

上面地址 的文件和项目, 在sts中无法启动, 修改后如下后可以工作,

iig-OAuth

另外, 由于本地 的8081被 nexus占用了, 因此 8081更换为9081, 8080更换9080了

测试基本可以。

项目结构非常简单,只有两个模块,分别是豆瓣和QQ,分别启动即可。

最终效果也非常简单清晰,下面显示效果

第一步

第二步

第三步

来源: https://www.cnblogs.com/flashsun/p/7424071.html

理解OAuth 2.0

OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版。

本文对OAuth 2.0的设计思路和运行流程,做一个简明通俗的解释,主要参考材料为RFC 6749。

简单介绍

OAuth 简介

OAuth 是由 Blaine Cook、Chris Messina、Larry Halff 及 David Recordon 共同发起的,目的在于为 API 访问授权提供一个安全、开放的标准。

基于 OAuth 认证授权具有以下特点:

  • 安全。OAuth 与别的授权方式不同之处在于:OAuth 的授权不会使消费方(Consumer)触及到用户的帐号信息(如用户名与密码),也是是说,消费方无需使用用户的用户名与密码就可以申请获得该用户资源的授权。
  • 开放。任何消费方都可以使用 OAuth 认证服务,任何服务提供方 (Service Provider) 都可以实现自身的 OAuth 认证服务。
  • 简单。不管是消费方还是服务提供方,都很容易于理解与使用。

OAuth 的解决方案如下图所示。

图 1. OAuth Solution

图 1. OAuth Solution

如 图 1 所示 OAuth 解决方案中用户、消费方及其服务提供方之间的三角关系:当用户需要 Consumer 为其提供某种服务时,该服务涉及到需要从服务提供方那里获取该用户的保护资源。OAuth 保证:只有在用户显式授权的情况下(步骤 4),消费方才可以获取该用户的资源,并用来服务于该用户。

从宏观层次来看,OAuth 按以下方式工作:

  1. 消费方与不同的服务提供方建立了关系。
  2. 消费方共享一个密码短语或者是公钥给服务提供方,服务提供方使用该公钥来确认消费方的身份。
  3. 消费方根据服务提供方将用户重定向到登录页面。
  4. 该用户登录后告诉服务提供方该消费方访问他的保护资源是没问题的。

 

一、应用场景

为了理解OAuth的适用场合,让我举一个假设的例子。

有一个"云冲印"的网站,可以将用户储存在Google的照片,冲印出来。用户为了使用该服务,必须让"云冲印"读取自己储存在Google上的照片。

云冲印

问题是只有得到用户的授权,Google才会同意"云冲印"读取这些照片。那么,"云冲印"怎样获得用户的授权呢?

传统方法是,用户将自己的Google用户名和密码,告诉"云冲印",后者就可以读取用户的照片了。这样的做法有以下几个严重的缺点。

(1)"云冲印"为了后续的服务,会保存用户的密码,这样很不安全。

(2)Google不得不部署密码登录,而我们知道,单纯的密码登录并不安全。

(3)"云冲印"拥有了获取用户储存在Google所有资料的权力,用户没法限制"云冲印"获得授权的范围和有效期。

(4)用户只有修改密码,才能收回赋予"云冲印"的权力。但是这样做,会使得其他所有获得用户授权的第三方应用程序全部失效。

(5)只要有一个第三方应用程序被破解,就会导致用户密码泄漏,以及所有被密码保护的数据泄漏。

OAuth就是为了解决上面这些问题而诞生的。

二、名词定义

在详细讲解OAuth 2.0之前,需要了解几个专用名词。它们对读懂后面的讲解,尤其是几张图,至关重要。

(1) Third-party application:第三方应用程序,本文中又称"客户端"(client),即上一节例子中的"云冲印"。

(2)HTTP service:HTTP服务提供商,本文中简称"服务提供商",即上一节例子中的Google。

(3)Resource Owner:资源所有者,本文中又称"用户"(user)。

(4)User Agent:用户代理,本文中就是指浏览器。

(5)Authorization server:认证服务器,即服务提供商专门用来处理认证的服务器。

(6)Resource server:资源服务器,即服务提供商存放用户生成的资源的服务器。它与认证服务器,可以是同一台服务器,也可以是不同的服务器。

知道了上面这些名词,就不难理解,OAuth的作用就是让"客户端"安全可控地获取"用户"的授权,与"服务商提供商"进行互动。

三、OAuth的思路

OAuth在"客户端"与"服务提供商"之间,设置了一个授权层(authorization layer)。"客户端"不能直接登录"服务提供商",只能登录授权层,以此将用户与客户端区分开来。"客户端"登录授权层所用的令牌(token),与用户的密码不同。用户可以在登录的时候,指定授权层令牌的权限范围和有效期。

"客户端"登录授权层以后,"服务提供商"根据令牌的权限范围和有效期,向"客户端"开放用户储存的资料。

四、运行流程

OAuth 2.0的运行流程如下图,摘自RFC 6749。

OAuth运行流程

(A)用户打开客户端以后,客户端要求用户给予授权。

(B)用户同意给予客户端授权。

(C)客户端使用上一步获得的授权,向认证服务器申请令牌。

(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。

(E)客户端使用令牌,向资源服务器申请获取资源。

(F)资源服务器确认令牌无误,同意向客户端开放资源。

不难看出来,上面六个步骤之中,B是关键,即用户怎样才能给于客户端授权。有了这个授权以后,客户端就可以获取令牌,进而凭令牌获取资源。

其实还是 比较难理解, 用下面的例子, 看看是否能明白

OAuth2.0是什么

OAuth2.0是什么——豆瓣和QQ的故事

OAuth简单说就是一种授权的协议,只要授权方和被授权方遵守这个协议去写代码提供服务,那双方就是实现了OAuth模式。

举个例子,你想登录豆瓣去看看电影评论,但你丫的从来没注册过豆瓣账号,又不想新注册一个再使用豆瓣,怎么办呢?不用担心,豆瓣已经为你这种懒人做了准备,用你的qq号可以授权给豆瓣进行登录,请看。

第一步:在豆瓣官网点击用qq登录

第二步:跳转到qq登录页面输入用户名密码,然后点授权并登录

第三步:跳回到豆瓣页面,成功登录

这几秒钟之内发生的事情,在无知的用户视角看来,就是在豆瓣官网上输了个qq号和密码就登录成功了。在一些细心的用户视角看来,页面经历了从豆瓣到qq,再从qq到豆瓣的两次页面跳转。但作为一群专业的程序员,我们还应该从上帝视角来看这个过程。

OAuth2.0是什么——上帝视角

简单来说,上述例子中的豆瓣就是客户端,QQ就是认证服务器,OAuth2.0就是客户端和认证服务器之间由于相互不信任而产生的一个授权协议。呵呵,要是相互信任那QQ直接把自己数据库给豆瓣好了,你直接在豆瓣输入qq账号密码查下数据库验证就登陆呗,还跳来跳去的多麻烦。

先上一张图,该图描绘了只几秒钟发生的所有事情用上帝视角来看的流程

就这这张图,来说一下上述例子中的三个步骤在图中的表现。所用到的请求路径名称都是虚构的,所附带的请求参数忽略了一些非重点的。

 

下面一一讲解客户端获取授权的四种模式。

五、客户端的授权模式

客户端必须得到用户的授权(authorization grant),才能获得令牌(access token)。OAuth 2.0定义了四种授权方式。

  • 授权码模式(authorization code)
  • 简化模式(implicit)
  • 密码模式(resource owner password credentials)
  • 客户端模式(client credentials)

六、授权码模式

授权码模式(authorization code)是功能最完整、流程最严密的授权模式。它的特点就是通过客户端的后台服务器,与"服务提供商"的认证服务器进行互动。

授权码模式

它的步骤如下:

(A)用户访问客户端,后者将前者导向认证服务器。

(B)用户选择是否给予客户端授权。

(C)假设用户给予授权,认证服务器将用户导向客户端事先指定的"重定向URI"(redirection URI),同时附上一个授权码。

(D)客户端收到授权码,附上早先的"重定向URI",向认证服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。

(E)认证服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)。

下面是上面这些步骤所需要的参数。

A步骤中,客户端申请认证的URI,包含以下参数:

  • response_type:表示授权类型,必选项,此处的值固定为"code"
  • client_id:表示客户端的ID,必选项
  • redirect_uri:表示重定向URI,可选项
  • scope:表示申请的权限范围,可选项
  • state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。

下面是一个例子。


GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz
        &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Host: server.example.com

C步骤中,服务器回应客户端的URI,包含以下参数:

  • code:表示授权码,必选项。该码的有效期应该很短,通常设为10分钟,客户端只能使用该码一次,否则会被授权服务器拒绝。该码与客户端ID和重定向URI,是一一对应关系。
  • state:如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。

下面是一个例子。


HTTP/1.1 302 Found
Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA
          &state=xyz

D步骤中,客户端向认证服务器申请令牌的HTTP请求,包含以下参数:

  • grant_type:表示使用的授权模式,必选项,此处的值固定为"authorization_code"。
  • code:表示上一步获得的授权码,必选项。
  • redirect_uri:表示重定向URI,必选项,且必须与A步骤中的该参数值保持一致。
  • client_id:表示客户端ID,必选项。

下面是一个例子。


POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb

E步骤中,认证服务器发送的HTTP回复,包含以下参数:

  • access_token:表示访问令牌,必选项。
  • token_type:表示令牌类型,该值大小写不敏感,必选项,可以是bearer类型或mac类型。
  • expires_in:表示过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。
  • refresh_token:表示更新令牌,用来获取下一次的访问令牌,可选项。
  • scope:表示权限范围,如果与客户端申请的范围一致,此项可省略。

下面是一个例子。


     HTTP/1.1 200 OK
     Content-Type: application/json;charset=UTF-8
     Cache-Control: no-store
     Pragma: no-cache

     {
       "access_token":"2YotnFZFEjr1zCsicMWpAA",
       "token_type":"example",
       "expires_in":3600,
       "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
       "example_parameter":"example_value"
     }

从上面代码可以看到,相关参数使用JSON格式发送(Content-Type: application/json)。此外,HTTP头信息中明确指定不得缓存。

七、简化模式

简化模式(implicit grant type)不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,跳过了"授权码"这个步骤,因此得名。所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。

简化模式

它的步骤如下:

(A)客户端将用户导向认证服务器。

(B)用户决定是否给于客户端授权。

(C)假设用户给予授权,认证服务器将用户导向客户端指定的"重定向URI",并在URI的Hash部分包含了访问令牌。

(D)浏览器向资源服务器发出请求,其中不包括上一步收到的Hash值。

(E)资源服务器返回一个网页,其中包含的代码可以获取Hash值中的令牌。

(F)浏览器执行上一步获得的脚本,提取出令牌。

(G)浏览器将令牌发给客户端。

下面是上面这些步骤所需要的参数。

A步骤中,客户端发出的HTTP请求,包含以下参数:

  • response_type:表示授权类型,此处的值固定为"token",必选项。
  • client_id:表示客户端的ID,必选项。
  • redirect_uri:表示重定向的URI,可选项。
  • scope:表示权限范围,可选项。
  • state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。

下面是一个例子。


    GET /authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz
        &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
    Host: server.example.com

C步骤中,认证服务器回应客户端的URI,包含以下参数:

  • access_token:表示访问令牌,必选项。
  • token_type:表示令牌类型,该值大小写不敏感,必选项。
  • expires_in:表示过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。
  • scope:表示权限范围,如果与客户端申请的范围一致,此项可省略。
  • state:如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。

下面是一个例子。


     HTTP/1.1 302 Found
     Location: http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA
               &state=xyz&token_type=example&expires_in=3600

在上面的例子中,认证服务器用HTTP头信息的Location栏,指定浏览器重定向的网址。注意,在这个网址的Hash部分包含了令牌。

根据上面的D步骤,下一步浏览器会访问Location指定的网址,但是Hash部分不会发送。接下来的E步骤,服务提供商的资源服务器发送过来的代码,会提取出Hash中的令牌。

八、密码模式

密码模式(Resource Owner Password Credentials Grant)中,用户向客户端提供自己的用户名和密码。客户端使用这些信息,向"服务商提供商"索要授权。

在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分,或者由一个著名公司出品。而认证服务器只有在其他授权模式无法执行的情况下,才能考虑使用这种模式。

密码模式

它的步骤如下:

(A)用户向客户端提供用户名和密码。

(B)客户端将用户名和密码发给认证服务器,向后者请求令牌。

(C)认证服务器确认无误后,向客户端提供访问令牌。

B步骤中,客户端发出的HTTP请求,包含以下参数:

  • grant_type:表示授权类型,此处的值固定为"password",必选项。
  • username:表示用户名,必选项。
  • password:表示用户的密码,必选项。
  • scope:表示权限范围,可选项。

下面是一个例子。


     POST /token HTTP/1.1
     Host: server.example.com
     Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
     Content-Type: application/x-www-form-urlencoded

     grant_type=password&username=johndoe&password=A3ddj3w

C步骤中,认证服务器向客户端发送访问令牌,下面是一个例子。


     HTTP/1.1 200 OK
     Content-Type: application/json;charset=UTF-8
     Cache-Control: no-store
     Pragma: no-cache

     {
       "access_token":"2YotnFZFEjr1zCsicMWpAA",
       "token_type":"example",
       "expires_in":3600,
       "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
       "example_parameter":"example_value"
     }

上面代码中,各个参数的含义参见《授权码模式》一节。

整个过程中,客户端不得保存用户的密码。

九、客户端模式

客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向"服务提供商"进行认证。严格地说,客户端模式并不属于OAuth框架所要解决的问题。在这种模式中,用户直接向客户端注册,客户端以自己的名义要求"服务提供商"提供服务,其实不存在授权问题。

客户端模式

它的步骤如下:

(A)客户端向认证服务器进行身份认证,并要求一个访问令牌。

(B)认证服务器确认无误后,向客户端提供访问令牌。

A步骤中,客户端发出的HTTP请求,包含以下参数:

  • granttype:表示授权类型,此处的值固定为"clientcredentials",必选项。
  • scope:表示权限范围,可选项。

     POST /token HTTP/1.1
     Host: server.example.com
     Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
     Content-Type: application/x-www-form-urlencoded

     grant_type=client_credentials

认证服务器必须以某种方式,验证客户端身份。

B步骤中,认证服务器向客户端发送访问令牌,下面是一个例子。


     HTTP/1.1 200 OK
     Content-Type: application/json;charset=UTF-8
     Cache-Control: no-store
     Pragma: no-cache

     {
       "access_token":"2YotnFZFEjr1zCsicMWpAA",
       "token_type":"example",
       "expires_in":3600,
       "example_parameter":"example_value"
     }

上面代码中,各个参数的含义参见《授权码模式》一节。

十、更新令牌

如果用户访问的时候,客户端的"访问令牌"已经过期,则需要使用"更新令牌"申请一个新的访问令牌。

客户端发出更新令牌的HTTP请求,包含以下参数:

  • granttype:表示使用的授权模式,此处的值固定为"refreshtoken",必选项。
  • refresh_token:表示早前收到的更新令牌,必选项。
  • scope:表示申请的授权范围,不可以超出上一次申请的范围,如果省略该参数,则表示与上一次一致。

下面是一个例子。


     POST /token HTTP/1.1
     Host: server.example.com
     Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
     Content-Type: application/x-www-form-urlencoded

     grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA 

另外, oauth2.0 有很多类型, 如下

OAuth 2.0 Client Types

Jakob Jenkov
Last update: 2014-06-15

The OAuth 2.0 client role is subdivided into a set of client types and profiles. This text will explain these types and profiles.

The OAuth 2.0 specification defines two types of clients:

  • Confidential
  • Public

A confidential client is an application that is capable of keeping a client password confidential to the world. This client password is assigned to the client app by the authorization server. This password is used to identify the client to the authorization server, to avoid fraud. An example of a confidential client could be a web app, where no one but the administrator can get access to the server, and see the client password.

A public client is an application that is not capable of keeping a client password confidential. For instance, a mobile phone application or a desktop application that has the client password embedded inside it. Such an application could get cracked, and this could reveal the password. The same is true for a JavaScript application running in the users browser. The user could use a JavaScript debugger to look into the application, and see the client password.

Client Profiles

The OAuth 2.0 specification also mentions a set of client profiles. These profiles are concrete types of applications, that can be either confidential or public. The profiles are:

  • Web Application
  • User Agent
  • Native

Web Application

A web application is an application running on a web server. In reality, a web application typically consists of both a browser part and a server part. If a web application needs access to a resource server (e.g. to Facebook user accounts), then the client password could be stored on the server. The password would thus be confidential.

Here is an illustration of a confidential client web application:

Confidential client: Web Application.

User Agent Application

A user agent application is for instance a JavaScript application running in a browser. The browser is the user agent. A user agent application may be stored on a web server, but the application is only running in the user agent once downloaded. An example could be a little JavaScript game that only runs in the browser.

Here is an illustration of a client user agent application:

Public client: User Agent Application.

Native Application

A native application is for instance a desktop application or a mobile phone application. Native applications are typically installed on the users computer or device (phone, tablet etc.). Thus, the client password will be stored on the users computer or device too.

Here is an illustration of a client native application:

Public client: Native Application.

 

Hybrid Applications

Some applications are hybrids of these profiles. For instance, a native application can have a server part too, that does part of the work (e.g. store data). The OAuth 2.0 specification says nothing about such hybrids. However, in most cases a hybrid will be able to use the authentication models of one of these profiles.

上述资料内容来源: http://tutorials.jenkov.com/oauth2/client-types.html

 

作者: 阮一峰