架构师之路-如何构建rest接口的安全性访问(dubbox+oatuh2+rest)

建立oauth2认证需要的数据库及数据表结构

CREATE SCHEMA IF NOT EXISTS `oauth2` DEFAULT CHARACTER SET utf8 ;

USE `oauth2` ;

 

-- -----------------------------------------------------

-- Table `oauth2`.`clientdetails`

-- -----------------------------------------------------

CREATE TABLE IF NOT EXISTS `oauth2`.`clientdetails` (

  `appId` VARCHAR(128) NOT NULL,

  `resourceIds` VARCHAR(256) NULL DEFAULT NULL,

  `appSecret` VARCHAR(256) NULL DEFAULT NULL,

  `scope` VARCHAR(256) NULL DEFAULT NULL,

  `grantTypes` VARCHAR(256) NULL DEFAULT NULL,

  `redirectUrl` VARCHAR(256) NULL DEFAULT NULL,

  `authorities` VARCHAR(256) NULL DEFAULT NULL,

  `access_token_validity` INT(11) NULL DEFAULT NULL,

  `refresh_token_validity` INT(11) NULL DEFAULT NULL,

  `additionalInformation` VARCHAR(4096) NULL DEFAULT NULL,

  `autoApproveScopes` VARCHAR(256) NULL DEFAULT NULL,

  PRIMARY KEY (`appId`))

ENGINE = InnoDB

DEFAULT CHARACTER SET = utf8;

 

 

-- -----------------------------------------------------

-- Table `oatuh2`.`oauth_access_token`

-- -----------------------------------------------------

CREATE TABLE IF NOT EXISTS `oauth2`.`oauth_access_token` (

  `token_id` VARCHAR(256) NULL DEFAULT NULL,

  `token` BLOB NULL DEFAULT NULL,

  `authentication_id` VARCHAR(128) NOT NULL,

  `user_name` VARCHAR(256) NULL DEFAULT NULL,

  `client_id` VARCHAR(256) NULL DEFAULT NULL,

  `authentication` BLOB NULL DEFAULT NULL,

  `refresh_token` VARCHAR(256) NULL DEFAULT NULL,

  PRIMARY KEY (`authentication_id`))

ENGINE = InnoDB

DEFAULT CHARACTER SET = utf8;

 

 

-- -----------------------------------------------------

-- Table `oatuh2`.`oauth_approvals`

-- -----------------------------------------------------

CREATE TABLE IF NOT EXISTS `oauth2`.`oauth_approvals` (

  `userId` VARCHAR(256) NULL DEFAULT NULL,

  `clientId` VARCHAR(256) NULL DEFAULT NULL,

  `scope` VARCHAR(256) NULL DEFAULT NULL,

  `status` VARCHAR(10) NULL DEFAULT NULL,

  `expiresAt` DATETIME NULL DEFAULT NULL,

  `lastModifiedAt` DATETIME NULL DEFAULT NULL)

ENGINE = InnoDB

DEFAULT CHARACTER SET = utf8;

 

 

-- -----------------------------------------------------

-- Table `oatuh2`.`oauth_client_details`

-- -----------------------------------------------------

CREATE TABLE IF NOT EXISTS `oauth2`.`oauth_client_details` (

  `client_id` VARCHAR(128) NOT NULL,

  `resource_ids` VARCHAR(256) NULL DEFAULT NULL,

  `client_secret` VARCHAR(256) NULL DEFAULT NULL,

  `scope` VARCHAR(256) NULL DEFAULT NULL,

  `authorized_grant_types` VARCHAR(256) NULL DEFAULT NULL,

  `web_server_redirect_uri` VARCHAR(256) NULL DEFAULT NULL,

  `authorities` VARCHAR(256) NULL DEFAULT NULL,

  `access_token_validity` INT(11) NULL DEFAULT NULL,

  `refresh_token_validity` INT(11) NULL DEFAULT NULL,

  `additional_information` VARCHAR(4096) NULL DEFAULT NULL,

  `autoapprove` VARCHAR(256) NULL DEFAULT NULL,

  PRIMARY KEY (`client_id`))

ENGINE = InnoDB

DEFAULT CHARACTER SET = utf8;

 

 

-- -----------------------------------------------------

-- Table `oatuh2`.`oauth_client_token`

-- -----------------------------------------------------

CREATE TABLE IF NOT EXISTS `oauth2`.`oauth_client_token` (

  `token_id` VARCHAR(256) NULL DEFAULT NULL,

  `token` BLOB NULL DEFAULT NULL,

  `authentication_id` VARCHAR(128) NOT NULL,

  `user_name` VARCHAR(256) NULL DEFAULT NULL,

  `client_id` VARCHAR(256) NULL DEFAULT NULL,

  PRIMARY KEY (`authentication_id`))

ENGINE = InnoDB

DEFAULT CHARACTER SET = utf8;

 

 

-- -----------------------------------------------------

-- Table `oatuh2`.`oauth_code`

-- -----------------------------------------------------

CREATE TABLE IF NOT EXISTS `oauth2`.`oauth_code` (

  `code` VARCHAR(256) NULL DEFAULT NULL,

  `authentication` BLOB NULL DEFAULT NULL)

ENGINE = InnoDB

DEFAULT CHARACTER SET = utf8;

 

 

-- -----------------------------------------------------

-- Table `oatuh2`.`oauth_refresh_token`

-- -----------------------------------------------------

CREATE TABLE IF NOT EXISTS `oauth2`.`oauth_refresh_token` (

  `token_id` VARCHAR(256) NULL DEFAULT NULL,

  `token` BLOB NULL DEFAULT NULL,

  `authentication` BLOB NULL DEFAULT NULL)

ENGINE = InnoDB

DEFAULT CHARACTER SET = utf8;

 

>>前提:  使用Maven来管理项目; spring-security-oauth的版本号为 2.0.10.RELEASE

1. 添加Maven dependencies; 以下只列出了主要的

  1.   
  2. <dependency>  
  3.     <groupId>org.springframework.securitygroupId>  
  4.     <artifactId>spring-security-coreartifactId>  
  5.     <version>${spring.security.version}version>  
  6. dependency>  
  7. <dependency>  
  8.     <groupId>org.springframework.securitygroupId>  
  9.     <artifactId>spring-security-webartifactId>  
  10.     <version>${spring.security.version}version>  
  11. dependency>  
  12. <dependency>  
  13.     <groupId>org.springframework.securitygroupId>  
  14.     <artifactId>spring-security-taglibsartifactId>  
  15.     <version>${spring.security.version}version>  
  16. dependency>  
  17. <dependency>  
  18.     <groupId>org.springframework.securitygroupId>  
  19.     <artifactId>spring-security-aclartifactId>  
  20.     <version>${spring.security.version}version>  
  21. dependency>  
  22. <dependency>  
  23.     <groupId>org.springframework.securitygroupId>  
  24.     <artifactId>spring-security-cryptoartifactId>  
  25.     <version>${spring.security.version}version>  
  26. dependency>  
  27. <dependency>  
  28.     <groupId>org.springframework.securitygroupId>  
  29.     <artifactId>spring-security-configartifactId>  
  30.     <version>${spring.security.version}version>  
  31. dependency>  
  32.   
  33. <dependency>  
  34.     <groupId>org.springframework.security.oauthgroupId>  
  35.     <artifactId>spring-security-oauth2artifactId>  
  36.     <version>1.0.5.RELEASEversion>  
  37. dependency>  

2. web.xml配置; 这一步与只使用Spring Security的配置一样.

  1. pre><pre code_snippet_id="73897" snippet_file_name="blog_20131119_2_2257675" name="code" class="html">    <filter>  
  2.         <filter-name>springSecurityFilterChainfilter-name>  
  3.         <filter-class>org.springframework.web.filter.DelegatingFilterProxyfilter-class>  
  4.     filter>  
  5.   
  6.     <filter-mapping>  
  7.         <filter-name>springSecurityFilterChainfilter-name>  
  8.         <url-pattern>/*url-pattern>  
  9.     filter-mapping>  
  10.   
  11.       
  12.     <context-param>  
  13.         <param-name>contextConfigLocationparam-name>  
  14.         <param-value>classpath:spring/*.xmlparam-value>  
  15.     context-param>  
  16.   
  17.       
  18.     <listener>  
  19.         <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>  
  20.     listener>  
  21.   
  22.       
  23.     <servlet>  
  24.         <servlet-name>hyservlet-name>  
  25.         <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>  
  26.         <load-on-startup>2load-on-startup>  
  27.     servlet>  
  28.     <servlet-mapping>  
  29.         <servlet-name>hyservlet-name>  
  30.         <url-pattern>/url-pattern>  
  31.     servlet-mapping>  

对于Spring MVC, 需要配置文件hy-servlet.xml, 该文件不是这儿关注的(忽略); 

在classpath创建spring目录, 在该目录里创建 security.xml 文件, 这是所有步骤配置的重点.

3.security.xml的配置; 重点开始.

3.1 起用注解; TokenEndpoint与AuthorizationEndpoint需要

  1. <mvc:annotation-driven/>  
  2. <mvc:default-servlet-handler/>  

3.2  TokenServices 配置

   1). TokenStore, 使用JdbcTokenStore, 将token信息存放数据库, 需要提供一个dataSource对象; 也可使用InMemoryTokenStore存于内存中

  1.   
  2. <beans:bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.JdbcTokenStore">  
  3.     <beans:constructor-arg index="0" ref="dataSource"/>  
  4. beans:bean>  

注: 可以在spring-security-oauth2中找到对应的SQL脚本, 地址为https://github.com/spring-projects/spring-security-oauth/tree/master/spring-security-oauth2/src/test/resources, 目录中的schema.sql 即是. (以下不再说明SQL脚本的问题)

  2).TokenServices; 需要注入TokenStore

  1. <beans:bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">  
  2.     <beans:property name="tokenStore" ref="tokenStore"/>  
  3.     <beans:property name="supportRefreshToken" value="true"/>  
  4. beans:bean>  

      如果允许刷新token 请将supportRefreshToken 的值设置为true, 默认为不允许

3.3 ClientDetailsService 配置, 使用JdbcClientDetailsService, 也需要提供dataSource, 替换demo中直接配置在配置文件中

  1. <beans:bean id="clientDetailsService" class="org.springframework.security.oauth2.provider.JdbcClientDetailsService">  
  2.     <beans:constructor-arg index="0" ref="dataSource"/>  
  3. beans:bean>  

3.4 ClientDetailsUserDetailsService配置, 该类实现了Spring security中 UserDetailsService 接口

  1. <beans:bean id="oauth2ClientDetailsUserService"  
  2.             class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">  
  3.     <beans:constructor-arg ref="clientDetailsService"/>  
  4. beans:bean>  

3.5 OAuth2AuthenticationEntryPoint配置

  1. <beans:bean id="oauth2AuthenticationEntryPoint"  
  2.             class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"/>  

3.6 oauth2 AuthenticationManager配置; 在整个配置中,有两个AuthenticationManager需要配置

  1. <authentication-manager id="oauth2AuthenticationManager">  
  2.     <authentication-provider user-service-ref="oauth2ClientDetailsUserService"/>  
  3. authentication-manager>  

第二个AuthenticationManager用于向获取UserDetails信息, 

  1. <authentication-manager alias="authenticationManager">  
  2.     <authentication-provider user-service-ref="userService">  
  3.         <password-encoder hash="md5"/>  
  4.     authentication-provider>  
  5. authentication-manager>  

userService是一个实现UserDetailsService的Bean

3.7 OAuth2AccessDeniedHandler配置, 实现AccessDeniedHandler接口

  1. <beans:bean id="oauth2AccessDeniedHandler"  
  2.             class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler"/>  

3.8 UserApprovalHandler配置, 这儿使用DefaultUserApprovalHandler, 这里是实现client是否可信任的关键点,你可以扩展该接口来自定义approval行为

  1. <beans:bean id="oauthUserApprovalHandler" class="org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler">  
  2. beans:bean>  

3.9 authorization-server配置, 核心

  1. <oauth2:authorization-server client-details-service-ref="clientDetailsService" token-services-ref="tokenServices"  
  2.                              user-approval-handler-ref="oauthUserApprovalHandler">  
  3.     <oauth2:authorization-code/>  
  4.     <oauth2:implicit/>  
  5.     <oauth2:refresh-token/>  
  6.     <oauth2:client-credentials/>  
  7.     <oauth2:password/>  
  8. oauth2:authorization-server>  

该元素里面的每个标签可设置每一种authorized-grant-type的行为. 如disable refresh-token的配置为

  1. <oauth2:refresh-token disabled="true"/>  

3.10 Oauth2 AccessDecisionManager配置, 这儿在默认的Spring Security AccessDecisionManager的基础上添加了ScopeVoter

  1. <beans:bean id="oauth2AccessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">  
  2.     <beans:constructor-arg>  
  3.         <beans:list>  
  4.             <beans:bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter"/>  
  5.             <beans:bean class="org.springframework.security.access.vote.RoleVoter"/>  
  6.             <beans:bean class="org.springframework.security.access.vote.AuthenticatedVoter"/>  
  7.         beans:list>  
  8.     beans:constructor-arg>  
  9. beans:bean>  

3.11 resource-server配置, 这儿定义两咱不同的resource

  1.   
  2. <oauth2:resource-server id="unityResourceServer" resource-id="unity-resource" token-services-ref="tokenServices"/>  
  3.   
  4.   
  5. <oauth2:resource-server id="mobileResourceServer" resource-id="mobile-resource" token-services-ref="tokenServices"/>  

注意: 每个resource-id的值必须在对应的ClientDetails中resourceIds值中存在

3.12 ClientCredentialsTokenEndpointFilter配置, 该Filter将作用于Spring Security的chain 链条中

  1. <beans:bean id="clientCredentialsTokenEndpointFilter"  
  2.             class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">  
  3.     <beans:property name="authenticationManager" ref="oauth2AuthenticationManager"/>  
  4. beans:bean>  

3.13 /oauth/token 的http 配置, 用于监听该URL的请求, 核心

  1. <http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="oauth2AuthenticationManager"  
  2.       entry-point-ref="oauth2AuthenticationEntryPoint">  
  3.     <intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY"/>  
  4.     <anonymous enabled="false"/>  
  5.     <http-basic entry-point-ref="oauth2AuthenticationEntryPoint"/>  
  6.   
  7.     <custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER"/>  
  8.     <access-denied-handler ref="oauth2AccessDeniedHandler"/>  
  9. http>  

3.14 针对不同resource的http配置, 由于上面配置了两个resource, 这儿也配置两个

  1.   
  2. <http pattern="/unity/**" create-session="never" entry-point-ref="oauth2AuthenticationEntryPoint"  
  3.       access-decision-manager-ref="oauth2AccessDecisionManager">  
  4.     <anonymous enabled="false"/>  
  5.   
  6.     <intercept-url pattern="/unity/**" access="ROLE_UNITY,SCOPE_READ"/>  
  7.   
  8.     <custom-filter ref="unityResourceServer" before="PRE_AUTH_FILTER"/>  
  9.     <access-denied-handler ref="oauth2AccessDeniedHandler"/>  
  10. http>  
  11.   
  12.   
  13. <http pattern="/m/**" create-session="never" entry-point-ref="oauth2AuthenticationEntryPoint"  
  14.       access-decision-manager-ref="oauth2AccessDecisionManager">  
  15.     <anonymous enabled="false"/>  
  16.   
  17.     <intercept-url pattern="/m/**" access="ROLE_MOBILE,SCOPE_READ"/>  
  18.   
  19.     <custom-filter ref="mobileResourceServer" before="PRE_AUTH_FILTER"/>  
  20.     <access-denied-handler ref="oauth2AccessDeniedHandler"/>  
  21. http>  

注意每一个http对应不同的resourceServer. access-decison-manager-ref对应Oauth的AccessDecisionManager

3.15 默认的http配置,给/oauth/** 设置权限

  1. <http access-denied-page="/login.jsp?authorization_error=2" disable-url-rewriting="true"  
  2.       authentication-manager-ref="authenticationManager">  
  3.     <intercept-url pattern="/oauth/**" access="ROLE_USER,ROLE_UNITY,ROLE_MOBILE"/>  
  4.     <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>  
  5.   
  6.     <form-login authentication-failure-url="/login.jsp?authentication_error=1" default-target-url="/index.jsp"  
  7.                 login-page="/login.jsp" login-processing-url="/login.do"/>  
  8.     <logout logout-success-url="/index.jsp" logout-url="/logout.do"/>  
  9.     <anonymous/>  
  10. http>  

到此, securiy.xml 配置完毕.

当然,还有些额外的工作你需要做, 如配置dataSource, 创建数据库, 添加用户用户信息, 管理ClientDetails等等.

Oauth相关的数据都是存放在数据库, 我们就可以根据表结果创建domain来实现管理.

更多参考内容:http://www.roncoo.com/article/index

时间: 2024-09-19 09:53:58

架构师之路-如何构建rest接口的安全性访问(dubbox+oatuh2+rest)的相关文章

一名作曲专业毕业生的安全架构师之路

通往安全架构师的路有很多条,但首先对IT基础设施和数据保护的激情,是这条道路的必备动力之一. 安全架构师是负责维护企业计算机系统安全的人,因此还必须具备黑客思维,能够预测攻击者非授权访问公司系统会采用的战术.处在安全架构师位置上的任何人,都有必须加班的时候,而且要随时跟进最新安全威胁和可用工具.有时候,最终走上这个岗位的人,在他们年轻时并没有预见过这么一个职业方向. 杰罗德·布伦南,90年代考入俄亥俄州首都大学这所小型文理学院的时候,他是想成为电影工业中的一名作曲家的. 当时,计算机音乐是一门新

Varnish配置文件详解(架构师之路)_Linux

既然Varnish需要在多台服务器上缓存数据,就需要Varnish映射所有的URL到一台单独的主机. 复制代码 代码如下: backend webserver {  .host = "127.0.0.1";  .port = "80";  .connect_timeout = 4s;  .first_byte_timeout = 5s;  .between_bytes_timeout = 20s;  }  该块配置用于定义一台Varnish默认访问的后端服务器,当V

架构师之路

1.引言 机算机科学是一门应用科学,它的知识体系是典型的倒三角结构,所用的基础知识并不多,只是随着应用领域和方向的不同,产生了很多的分支,所以说编程并不是一件很困难的事情,一个高中生经过特定的训练就可以做得到.但是,会编程和编好程绝对是两码事,同样的程序员,有的人几年之后成为了架构师,有的人却还在不停地coding,只不过ctrl-c.ctrl-v用得更加纯熟了.在中国,编程人员最终的归途无外乎两条:一是转向技术管理,它的终点是CTO:二是继续深入,它的终点是首席架构师,成为CEO的人毕竟是少数

五年Skype架构师之路的感言

简介 作为架构师和设计者,我们常把手头的事情作为工作焦点,很少反思过去如何.我们应该温故而知新.我从作为skype架构组领导的55个月经历中总结了6个经验.其中一些是技术性的,另外一些是架构师较为软性的观点.首先介绍一下Skype的背景资料. Skype背景 Skype是让用户可以进行音频视频通话的软件,也可以拨打普通电话以及发送短消息.公司成立于2003年,从成立以后就有令人难以置信的成长曲线.公司现在有超过五亿两千万注册用户,大约650名员工.这些用户同时产生平均21万个通话,其中大约三分之

艾伟也谈项目管理,五年Skype架构师之路的感言

简介 作为架构师和设计者,我们常把手头的事情作为工作焦点,很少反思过去如何.我们应该温故而知新.我从作为skype架构组领导的55 个月经历中总结了6个经验.其中一些是技术性的,另外一些是架构师较为软性的观点.首先介绍一下Skype的背景资料. Skype背景 Skype是让用户可以进行音频视频通话的软件,也可以拨打普通电话以及发送短消息.公司成立于2003年,从成立以后就有令人难以置信的成长曲线.公司现在有超过五亿两千万注册用户,大约650名员工.这些用户同时产生平均21万个通话,其中大约三分

通向云架构师之路必备知识技能

云计算基本概述: 简单易用,通过网络交付的服务;云计算的本质 云计算服务类型: IAAS.PASS.SASS;层次性的划分,并不定是互相依赖,即PASS不定要依赖于IASS,SAAS不一定依赖于PASS; 云部署方式: 公有云.私有云.混合云 云计算特点: 使用 Cloud 说明云计算特点: C:-Cost Efficiency:高效低成本,虚似化技术; L-Large scale:海量,大规模 ; O-Optimized:应用类型优化 ; U-Usage centric:按需付费,类似水电的,

架构师之路-在Dubbo中开发REST风格的远程调用

概述 dubbo支持多种远程调用方式,例如dubbo RPC(二进制序列化 + tcp协议).http invoker(二进制序列化 + http协议,至少在开源版本没发现对文本序列化的支持).hessian(二进制序列化 + http协议).WebServices (文本序列化 + http协议)等等,但缺乏对当今特别流行的REST风格远程调用(文本序列化 + http协议)的支持. 有鉴于此,我们基于标准的Java REST API--JAX-RS 2.0(Java API for REST

架构师之路-创业互联网公司如何搭建自己的技术架构

适用范围 本文主要针对中小型互联网公司,特别适用于手机APP或者pc的后台架构,基本可以支撑5万日活 本文会对可能用到的相关技术进行技术选型的说明,以及技术的架构介绍,技术架构的介绍课程后面有地址,可以点进去查看. 技术指标 说一下一些技术指标的计算过程可以作为其他同学的参考 QPS, 如果是5万日活,使用集中在每天的4小时,每个用户大概产生100的请求,那么平均下来,我们系统大概应该支撑的请求为:50000 100 / (4 60 * 60) = 350 qps/s 业务数据 业务量,我们自己

架构师之路-如何建立高可用消息中间件kafka

Kafka 一.熟悉kafka l  Server-1 broker其实就是kafka的server,因为producer和consumer都要去连它.Broker主要还是做存储用. l  Server-2是zookeeper的server端,zookeeper的具体作用你可以去官网查,在这里你可以先想象,它维持了一张表,记录了各个节点的IP.端口等信息(以后还会讲到,它里面还存了kafka的相关信息). l  Server-3.4.5他们的共同之处就是都配置了zkClient,更明确的说,就是