在surging 微服务引擎下如何搭建webservice和身份验证
一、前言
现实生产中,有一些比较老的系统对外提供的接口都是WebService,尤其是比较老的系统都是围绕ESB进行搭建,而对外提供就需要WebService ,为了更好完善其解决方案,故集成了webservice 协议组件和身份验证,现把它上传至github, 而这篇文章就是讲述如何构建WebService,创建的接口IWebServiceService代码如下:
using Surging.Core.CPlatform.Ioc;
using Surging.Core.CPlatform.Runtime.Server.Implementation.ServiceDiscovery.Attributes;
using Surging.IModuleServices.Common.Models;
using System.ServiceModel;
using System.Threading.Tasks; namespace Surging.IModuleServices.Common
{
[ServiceBundle("api/{Service}/{Method}")]
[ServiceContract]
public interface IWebServiceService : IServiceKey
{
[OperationContract]
Task<string> SayHello(string name); [OperationContract]
Task<string> Authentication(AuthenticationRequestData requestData);
}
}
AuthenticationRequestData 代码如下:
using ProtoBuf;
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Text; namespace Surging.IModuleServices.Common.Models
{
[ProtoContract]
[DataContract]
public class AuthenticationRequestData
{
[ProtoMember(1)]
[DataMember]
public string UserName { get; set; } [ProtoMember(2)]
[DataMember]
public string Password { get; set; }
}
}
从以上代码来看,除了需要符合引擎代码规则外,还需要添加[ServiceContract]和[OperationContract] 特性, 如果参数是实体的话,需要添加在实体模型上加[DataContract]和 属性上加[DataMember]
那么创建的业务服务WebServiceService代码如下:
using Surging.Core.ApiGateWay.OAuth;
using Surging.Core.Protocol.WebService.Runtime;
using Surging.IModuleServices.Common;
using Surging.IModuleServices.Common.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Surging.Modules.Common.Domain
{
public class WebServiceService : WebServiceBehavior, IWebServiceService
{
private readonly IAuthorizationServerProvider _authorizationServerProvider;
public WebServiceService(IAuthorizationServerProvider authorizationServerProvider)
{
_authorizationServerProvider = authorizationServerProvider;
}
public async Task<string> SayHello(string name)
{
var token = this.HeaderValue.Token;
if (await _authorizationServerProvider.ValidateClientAuthentication(token))
return $"Hello,{name}";
else
return " Please leave, stranger";
} public async Task<string> Authentication(AuthenticationRequestData requestData)
{
var param = new Dictionary<string, object>();
param.Add("requestData", requestData);
var result= await _authorizationServerProvider.GenerateTokenCredential(param);
return result;
}
}
}
通过以上代码,首先需要继承IWebServiceService和WebServiceBehavior,然后通过IAuthorizationServerProvider 去生成Token 和验证Token, 或者也可以脱离引擎的身份鉴权,通过传递的this.HeaderValue.Token 进行验证。
通过访问127.0.0.1:289/api/webservice/sayhello.asmx,显示以下界面,说明基于webservice 的服务就已经添加成功。

二、引用WebService
首先我们在创建好的控制台项目里面添加WebService的引用。
1、在依赖项上面右键,选择“添加服务引用”,选择wcf web service如图所示:

添加服务引用。如图所示:
配置完以后,点击“下一步”,去掉重新使用引用的程序集中的类型签名的复选框。

直接点击“完成”按钮即可。慢慢等待配置完成:

配置完成界面如图所示:

下面就介绍如何在.net 6.0下调用webservice
三、调用WebService
在Program类文件中,调用webservice 提供的sayhello,在调用前需要生成token, 通过token才能正确访问结果,以下是基于.net 6.0,代码如下:
1 // See https://aka.ms/new-console-template for more information
2 using ConsoleApp7;
3 using ServiceReference1;
4 using System.ServiceModel;
5
6 try
7 {
8
9
10 WebServiceServiceClient client = new WebServiceServiceClient();
11 using (var scope = new FlowingOperationContextScope(client.InnerChannel))
12 {
13 var authenticationResponse = await client.AuthenticationAsync(new AuthenticationRequestData
14 {
15 UserName = "admin",
16 Password = "admin"
17 }).ContinueOnScope(scope);
18 var authenticationResult = authenticationResponse.Body.AuthenticationResult;
19 if (authenticationResponse.Body.AuthenticationResult != null)
20 {
21 var header1 = System.ServiceModel.Channels.MessageHeader.CreateHeader("headerValue", "http://tempuri.org/", new HeaderValue
22 {
23 Token = authenticationResult
24 });
25 OperationContext.Current.OutgoingMessageHeaders.Add(header1);
26 var sayHelloResponse =await client.SayHelloAsync("fanly").ContinueOnScope(scope);
27 Console.WriteLine(sayHelloResponse.Body.SayHelloResult);
28 Console.ReadLine();
29 }
30
31 }
32
33 }
34 catch (Exception ex)
35 {
36 Console.WriteLine(ex.Message);
37 }
以下是基于.net framework 调用webservice 的代码:
1 internal class Program
2 {
3 static async Task Main(string[] args)
4 {
5 try
6 {
7
8 WebServiceServiceClient client = new WebServiceServiceClient();
9 using (var scope = new OperationContextScope(client.InnerChannel))
10 {
11 var authenticationResponse = client.Authentication(new AuthenticationRequestData
12 {
13 UserName = "admin",
14 Password = "admin"
15 });
16 if (authenticationResponse != null)
17 {
18 var header1 = System.ServiceModel.Channels.MessageHeader.CreateHeader("headerValue", "http://tempuri.org/", new HeaderValue
19 {
20 Token = authenticationResponse
21 });
22 OperationContext.Current.OutgoingMessageHeaders.Add(header1);
23 var sayHelloResponse = client.SayHello("fanly");
24 Console.WriteLine(sayHelloResponse);
25 Console.ReadLine();
26 }
27
28 }
29
30 }
31 catch (Exception ex)
32 {
33 Console.WriteLine(ex.Message);
34 }
35 }
36 }
HeaderValue 代码如下:
namespace ConsoleApp7
{
public class HeaderValue
{
public string Token { get; set; }
}
}
因为.net 6.0 生成的代码是异步,所以就要修改OperationContextScope 以支持异步,代码如下:
1 public sealed class FlowingOperationContextScope : IDisposable
2 {
3 bool _inflight = false;
4 bool _disposed;
5 OperationContext _thisContext = null;
6 OperationContext _originalContext = null;
7
8 public FlowingOperationContextScope(IContextChannel channel):
9 this(new OperationContext(channel))
10 {
11 }
12
13 public FlowingOperationContextScope(OperationContext context)
14 {
15 _originalContext = OperationContext.Current;
16 OperationContext.Current = _thisContext = context;
17 }
18
19 public void Dispose()
20 {
21 if (!_disposed)
22 {
23 if (_inflight || OperationContext.Current != _thisContext)
24 throw new InvalidOperationException();
25 _disposed = true;
26 OperationContext.Current = _originalContext;
27 _thisContext = null;
28 _originalContext = null;
29 }
30 }
31
32 internal void BeforeAwait()
33 {
34 if (_inflight)
35 return;
36 _inflight = true;
37 }
38
39 internal void AfterAwait()
40 {
41 if (!_inflight)
42 throw new InvalidOperationException();
43 _inflight = false;
44 OperationContext.Current = _thisContext;
45 }
46 }
47
48 public static class TaskExt
49 {
50 public static SimpleAwaiter<TResult> ContinueOnScope<TResult>(this Task<TResult> @this, FlowingOperationContextScope scope)
51 {
52 return new SimpleAwaiter<TResult>(@this, scope.BeforeAwait, scope.AfterAwait);
53 }
54
55 public class SimpleAwaiter<TResult> :
56 System.Runtime.CompilerServices.INotifyCompletion
57 {
58 readonly Task<TResult> _task;
59
60 readonly Action _beforeAwait;
61 readonly Action _afterAwait;
62
63 public SimpleAwaiter(Task<TResult> task, Action beforeAwait, Action afterAwait)
64 {
65 _task = task;
66 _beforeAwait = beforeAwait;
67 _afterAwait = afterAwait;
68 }
69
70 public SimpleAwaiter<TResult> GetAwaiter()
71 {
72 return this;
73 }
74
75 public bool IsCompleted
76 {
77 get
78 {
79 if (_task.IsCompleted)
80 return true;
81 _beforeAwait();
82 return false;
83 }
84
85 }
86
87 public TResult GetResult()
88 {
89 return _task.Result;
90 }
91
92 // INotifyCompletion
93 public void OnCompleted(Action continuation)
94 {
95 _task.ContinueWith(task =>
96 {
97 _afterAwait();
98 continuation();
99 },
100 CancellationToken.None,
101 TaskContinuationOptions.ExecuteSynchronously,
102 SynchronizationContext.Current != null ?
103 TaskScheduler.FromCurrentSynchronizationContext() :
104 TaskScheduler.Current);
105 }
106 }
107 }
程序输出结果:

四、结尾
surging 正在开发微服务平台(以处于调试阶段),形成独立的项目产品,抛弃之前的代码架构的形式,现如今已经攘括支持WEB, 物联网,流媒体等多种业务场景, 现在开发支持了外层协议有:MQTT,Grpc,, DNS, TCP,UDP,restful,rtmp,httpflv,rtsp,websocket,webservice, 内部可以通过基于thrift 或者netty 做到可靠性的RPC调用,因为有服务治理,服务发现,并且支持了Apollo配置中心,skywalking 链路跟踪,并且支持JAVA和.NET主流开发语言,请大家多多留意surging 的微服务平台。或者你也可以加群联系到我:744677125(老群被封,这是新群)
在surging 微服务引擎下如何搭建webservice和身份验证的更多相关文章
- surging 微服务引擎 2.0 会有多少惊喜?
surging 微服务引擎从2017年6月至今已经有两年的时间,这两年时间有多家公司使用surging 服务引擎,并且有公司搭建了CI/CD,并且使用了k8s 集群,这里我可以说下几家公司的服务搭建情 ...
- 谈谈surging 微服务引擎 2.0的链路跟踪和其它新增功能
一.前言 surging是基于.NET CORE 服务引擎.初始版本诞生于2017年6月份,经过NCC社区二年的孵化,2.0版本将在2019年08月28日进行发布,经历二年的发展,已经全部攘括了微服务 ...
- surging 微服务引擎 -协议主机的Behavior特性
1.前言 因为工作的关系,最近很少更新surging,因为surging 一直处在不温不火的状态,而自己每天利用业余时间进行完善,每天都是疲惫的状态,还要应付新手的提问,曾经一度想放弃,但是有些人劝说 ...
- surging 微服务引擎 1.0 正式发布
surging 是一个分布式微服务引擎,提供高性能RPC远程服务调用,服务引擎支持http.TCP.WS.Mqtt协议,采用Zookeeper.Consul作为surging服务的注册中心,集成了哈希 ...
- CI Weekly #5 | 微服务架构下的持续部署与交付
CI Weekly 围绕『 软件工程效率提升』 进行一系列技术内容分享,包括国内外持续集成.持续交付,持续部署.自动化测试. DevOps 等实践教程.工具与资源,以及一些工程师文化相关的程序员 Ti ...
- 微服务架构下分布式Session管理
转载本文需注明出处:EAII企业架构创新研究院(微信号:eaworld),违者必究.如需加入微信群参与微课堂.架构设计与讨论直播请直接回复此公众号:“加群 姓名 公司 职位 微信号”. 一.应用架构变 ...
- CI Weekly #11 | 微服务场景下的自动化测试与持续部署
又一周过去了,最近我们的工程师正在搞一个"大事情" --「[flow.ci](http://flow.ci/?utm_source=bokeyuan&utm_medium= ...
- 微服务框架下的思维变化-OSS.Core基础思路
如今框架两字已经烂大街了,xx公司架构设计随处可见,不过大多看个热闹,这些框架如何来的,细节又是如何思考的,相互之间的隔离依据又是什么...相信很多朋友应该依然存在自己的疑惑,特别是越来越火热的微服务 ...
- SpringBoot微服务架构下的MVC模型总结
SpringBoot微服务架构下的MVC模型产生的原因: 微服务概念改变着软件开发领域,传统的开源框架结构开发,由于其繁琐的配置流程 , 复杂的设置行为,为项目的开发增加了繁重的工作量,微服务致力于解 ...
- 微服务架构下分布式事务解决方案——阿里GTS
1 微服务的发展 微服务倡导将复杂的单体应用拆分为若干个功能简单.松耦合的服务,这样可以降低开发难度.增强扩展性.便于敏捷开发.当前被越来越多的开发者推崇,很多互联网行业巨头.开源社区等都开始了微服务 ...
随机推荐
- Test Fixture框架结构
Test Fixture框架 1.结构: setup() testcase() teardown() 2.新建unittest文件,命名unittestdemo.py 1 import unittes ...
- noi 1.5 36 计算多项式的值
描述 假定多项式的形式为xn+xn-1+-+x2+x+1,请计算给定单精度浮点数x和正整数n值的情况下这个多项式的值. 输入 输入仅一行,包括x和n,用单个空格隔开.x在float范围内,n < ...
- Mixly智能门禁(物联网)
智能门禁arduino rc522读卡器 sg90舵机 校园卡我的校园卡号识别为 30fcb4a8d #include <RFID.h>#include <SPI.h>#in ...
- python 深拷贝及浅拷贝区别
深拷贝及浅拷贝区别 浅拷贝copy: 可变类型:(列表,字典,集合)copy函数对可变类型的第一层对象进行拷贝,对拷贝的对象开辟新的内存空间进行存储,不会拷贝对象内部的子对象 不可变类型:(数字,字符 ...
- zynq 中断
#include "stdio.h"#include "xparameters.h"#include "xgpiops.h"#include ...
- snpEFF注释的vcf文件转化成maf文件
利用一个perl语言写的工具:snpeffTomaf 一行代码即可实现非常方便 github地址链接:https://github.com/tsy19900929/snpeffToMaf 将此仓库中的 ...
- 机制设计原理与应用(三)Screening
目录 3 Screening 3.1 为单个不可分割的项目定价 3.1.1 对\(\theta\)的假设 3.1.2 问题描述 3.1.3 特性 3.2 为无限可分的项目定价 3.2.1 对\(\th ...
- Linux /proc 目录
/proc 目录 /proc 文件目录是一个伪文件,它只存在于系统内存中,而不占用外存空间.它以文件系统的方式为用户提供访问内核数据的操作接口.目录下主要包含进程和状态的信息. /proc 下文件含义 ...
- spring boot 中 CommandLineRunner接口使用
接口定义:接口,用于指示bean包含在SpringApplication中时应运行.可以在同一应用程序上下文中定义多个CommandLineRunner bean,并可以使用ordered接口或@Or ...
- 原来sed不支持非贪婪匹配
场景 从GISAID上面批量下载下来的序列id很长,格式如下: 太长了,并且makeblastdb的时候-parse_seqids参数会导致报错,大概是长度太长不符合要求无法处理之类的. 不作处理去掉 ...