聲明:
1. 本範例屬中高階工程技術範疇,不適合初學者。
2. 學習本範例需要對 Web API 有基礎的概念。
以下的範例主要是示範前端 (C#) 向後端 Web API (REST web service) 拿資料,而我們會提供需權限認證及免權限認證二類的資料來源,而權限認證我們是以令牌 (Token) 的方式進行控管的。
修改 Web API 的控制器 (ValuesController.cs) :
\Controllers\ValuesController.cs
using System;
using System.Web.Http;
namespace LocalAccountsApp.Controllers
{
[Authorize]
public class ValuesController : ApiController
{
// GET api/values
[AllowAnonymous]
[HttpGet]
[Route("api/GetValues")]
public string GetValues()
{
return "嗨, 您來了.(http get)";
}
[HttpGet]
[Route("api/GetAuthValues")]
public string GetAuthValues()
{
var userName = this.RequestContext.Principal.Identity.Name;
return String.Format("嗨, {0} 您來了.(http get)[by auth]", userName);
}
[AllowAnonymous]
[HttpPost]
[Route("api/PostValues")]
public string PostValues()
{
return "嗨, 您來了.(http post)";
}
[HttpPost]
[Route("api/PostAuthValues")]
public string PostAuthValues()
{
var userName = this.RequestContext.Principal.Identity.Name;
return String.Format("嗨, {0} 您來了.(http post)[by auth]", userName);
}
}
}
前端建立主控台應用程式專案,並修改 Program.cs :
\Program.cs
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace HttpWebRequestGetTokenByPasswordExample
{
public class MorseDataControl
{
MorseHttpWeb morseHttpWeb = new MorseHttpWeb();
#region Get
public string GetValues(string url)
{
return morseHttpWeb.GetHttpWeb(url);
}
public string GetAuthValues(string url, string accessToken)
{
return morseHttpWeb.GetHttpWeb(url, accessToken);
}
public async Task<string> GetValuesAsync(string url)
{
return await morseHttpWeb.GetHttpWebAsync(url);
}
public async Task<string> GetAuthValuesAsync(string url, string accessToken)
{
return await morseHttpWeb.GetHttpWebAsync(url, accessToken);
}
#endregion
#region Post
public string PostValues(string url, string query)
{
return morseHttpWeb.PostHttpWeb(url, query);
}
public async Task<string> PostValuesAsync(string url, string query)
{
return await morseHttpWeb.PostHttpWebAsync(url, query);
}
public string PostAuthValues(string url, string query, string accessToken)
{
return morseHttpWeb.PostHttpWeb(url, query, accessToken);
}
public async Task<string> PostAuthValuesAsync(string url, string query, string accessToken)
{
return await morseHttpWeb.PostHttpWebAsync(url, query, accessToken);
}
#endregion
}
public class MorseHttpWeb
{
/// <summary>
/// 取得令牌
/// </summary>
/// <param name="url"></param>
/// <param name="username"></param>
/// <param name="password"></param>
/// <returns>令牌 (Token)</returns>
public accessToken GetAccessToken(string url, string username, string password)
{
accessToken ret = new accessToken();
WebRequest request = HttpWebRequest.Create(url);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
// 方法1:
// NameValueCollection outgoingQueryString = HttpUtility.ParseQueryString(String.Empty);
// outgoingQueryString.Add("grant_type", "password");
// outgoingQueryString.Add("username", username);
// outgoingQueryString.Add("password", password);
// byte[] postBytes = new ASCIIEncoding().GetBytes(outgoingQueryString.ToString()); // 轉成 byte[]
//方法2:
string s = string.Format("username={0}&password={1}&grant_type=password", username, password);
byte[] postBytes = new ASCIIEncoding().GetBytes(s); // 轉成 byte[]
Stream postStream = request.GetRequestStream();//取得用以寫入要求資料的 Stream 物件。
postStream.Write(postBytes, 0, postBytes.Length);
postStream.Flush();
postStream.Close();
using(WebResponse response = request.GetResponse()) {
using(StreamReader streamReader = new StreamReader(response.GetResponseStream())) {
ret = JsonConvert.DeserializeObject<accessToken>(streamReader.ReadToEnd().Replace(".", ""));
}
}
return ret;
}
/// <summary>
/// 取得令牌(非同步)
/// </summary>
/// <param name="url"></param>
/// <param name="username"></param>
/// <param name="password"></param>
/// <returns>令牌 (Token)</returns>
public async Task<accessToken> GetAccessTokenAsync(string url, string username, string password)
{
accessToken ret = new accessToken();
WebRequest request = HttpWebRequest.Create(url);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
// 方法1:
// NameValueCollection outgoingQueryString = HttpUtility.ParseQueryString(String.Empty);
// outgoingQueryString.Add("grant_type", "password");
// outgoingQueryString.Add("username", username);
// outgoingQueryString.Add("password", password);
// byte[] postBytes = new ASCIIEncoding().GetBytes(outgoingQueryString.ToString()); // 轉成 byte[]
//方法2:
string s = string.Format("username={0}&password={1}&grant_type=password", username, password);
byte[] postBytes = new ASCIIEncoding().GetBytes(s); // 轉成 byte[]
Stream postStream = await request.GetRequestStreamAsync(); //傳回以非同步作業方式將資料寫入網際網路資源的 Stream
postStream.Write(postBytes, 0, postBytes.Length);
postStream.Flush();
postStream.Close();
using(WebResponse response = await request.GetResponseAsync()) {
using(StreamReader streamReader = new StreamReader(response.GetResponseStream())) {
ret = JsonConvert.DeserializeObject<accessToken>((await streamReader.ReadToEndAsync()).Replace(".", ""));
}
}
return ret;
}
/// <summary>
/// HTTP GET Method Process
/// </summary>
/// <param name="uri"></param>
/// <param name="accessToken">令牌 (Token)</param>
/// <returns></returns>
public string GetHttpWeb(string uri, string accessToken = null)
{
string retVal = "";
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);
request.Method = "GET";
if(accessToken != null)
request.Headers.Add("Authorization", "Bearer " + accessToken);
try {
using(var response = request.GetResponse())
if(response != null) {
var reader = new StreamReader(response.GetResponseStream());
if(reader != null)
retVal = reader.ReadToEnd();
}
}
catch(Exception ex) {
Console.WriteLine("Error: " + ex.ToString());
}
return retVal;
}
/// <summary>
/// HTTP GET Method Process(非同步)
/// </summary>
/// <param name="uri"></param>
/// <param name="accessToken">令牌 (Token)</param>
/// <returns></returns>
public async Task<string> GetHttpWebAsync(string uri, string accessToken = null)
{
string retVal = "";
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);
request.Method = "GET";
if(accessToken != null)
request.Headers.Add("Authorization", "Bearer " + accessToken);
try {
using(var response = await request.GetResponseAsync())
if(response != null) {
var reader = new StreamReader(response.GetResponseStream());
if(reader != null)
retVal = await reader.ReadToEndAsync();
}
}
catch(Exception ex) {
Console.WriteLine("Error: " + ex.ToString());
}
return retVal;
}
/// <summary>
/// HTTP POST Method Process
/// </summary>
/// <param name="post_url"></param>
/// <param name="post_query_string"></param>
/// <returns></returns>
public string PostHttpWeb(string post_url, string post_query_string, string accessToken = null)
{
var ret = "";
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(post_url);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
if(accessToken != null)
request.Headers.Add("Authorization", "Bearer " + accessToken);
try {
using(var writer = new StreamWriter(request.GetRequestStream())) writer.Write(post_query_string);
using(var response = request.GetResponse()) {
var reader = new StreamReader(response.GetResponseStream());
if(reader != null)
ret = reader.ReadToEnd();
}
}
catch(Exception ex) {
Console.WriteLine("Error: " + ex.ToString());
}
return ret;
}
/// <summary>
/// HTTP POST Method Process(非同步)
/// </summary>
/// <param name="post_url"></param>
/// <param name="post_query_string"></param>
/// <param name="accessToken">令牌 (Token)</param>
/// <returns></returns>
public async Task<string> PostHttpWebAsync(string post_url, string post_query_string, string accessToken = null)
{
var ret = "";
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(post_url);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
if(accessToken != null)
request.Headers.Add("Authorization", "Bearer " + accessToken);
try {
using(var writer = new StreamWriter(await request.GetRequestStreamAsync())) writer.Write(post_query_string);
using(var response = await request.GetResponseAsync()) {
var reader = new StreamReader(response.GetResponseStream());
if(reader != null)
ret = await reader.ReadToEndAsync();
}
}
catch(Exception ex) {
Console.WriteLine("Error: " + ex.ToString());
}
return ret;
}
}
public class MorseProcess
{
public MorseProcess()
{
}
public async Task HttpWebTest() {
string userName = "xxxxxx@gmail.com";
string userPassword = "xxxxxx";
string urlString = "https://localhost:8087/token";
Console.WriteLine((new MorseDataControl()).GetValues("https://localhost:8087/api/GetValues"));
Console.WriteLine(await (new MorseDataControl()).GetValuesAsync("https://localhost:8087/api/GetValues"));
Console.WriteLine((new MorseDataControl()).PostValues("https://localhost:8087/api/PostValues", ""));
Console.WriteLine(await (new MorseDataControl()).PostValuesAsync("https://localhost:8087/api/PostValues", ""));
accessToken t = (new MorseHttpWeb()).GetAccessToken(urlString, userName, userPassword); // 令牌
accessToken tAsync = (new MorseHttpWeb()).GetAccessToken(urlString, userName, userPassword); // 令牌
Console.WriteLine("Token 1: " + t.access_token);
Console.WriteLine("Token 2: " + tAsync.access_token);
Console.WriteLine((new MorseDataControl()).GetAuthValues("https://localhost:8087/api/GetAuthValues", t.access_token));
Console.WriteLine(await (new MorseDataControl()).GetAuthValuesAsync("https://localhost:8087/api/GetAuthValues", t.access_token));
Console.WriteLine((new MorseDataControl()).PostAuthValues("https://localhost:8087/api/PostAuthValues", "", t.access_token));
Console.WriteLine(await (new MorseDataControl()).PostAuthValuesAsync("https://localhost:8087/api/PostAuthValues", "", t.access_token));
}
}
class Program
{
static void Main(string[] args)
{
(new MorseProcess()).HttpWebTest().Wait();
Console.Write("Press any key...");
Console.ReadKey();
}
}
public class accessToken
{
public dynamic access_token { get; set; }
public string token_type { get; set; }
public int expires_in { get; set; }
public string userName { get; set; }
public DateTime issued { get; set; }
public DateTime expires { get; set; }
}
}
執行結果: