我也在web API上工作,通過手機用戶可以連接到它。 對於Authentication
我在.net中使用RSA
。手機客戶端首先發送用戶名和密碼,然後創建令牌並將其發送給客戶端。在接下來的請求中,客戶端必須將此令牌附加到請求標頭,並且我得到此令牌並從中提取用戶名和密碼。
RSA加密:
public class ApiRSA
{
private static string privateKey = // Generate a private key
private static string publicKey = // Generate a public key
public static string Decrypt(string data)
{
var rsa = new RSACryptoServiceProvider();
byte[] dataByte = Convert.FromBase64String(data);
rsa.FromXmlString(privateKey);
var decryptedByte = rsa.Decrypt(dataByte, false);
return Encoding.Unicode.GetString(decryptedByte);
}
public static string Encrypt(string data)
{
var rsa = new RSACryptoServiceProvider();
var dataByte = Encoding.Unicode.GetBytes(data);
rsa.FromXmlString(publicKey);
var encryptedByte = rsa.Encrypt(dataByte, false);
return Convert.ToBase64String(encryptedByte);
}
public static void GeneraterPrivatePublicKey(out string privateKey, out string publicKey)
{
var csp = new RSACryptoServiceProvider(1024);
var privKey = csp.ExportParameters(true);
var pubKey = csp.ExportParameters(false);
{
var sw = new System.IO.StringWriter();
var xs = new System.Xml.Serialization.XmlSerializer(typeof(RSAParameters));
xs.Serialize(sw, privKey);
privateKey = sw.ToString();
}
{
var sw = new System.IO.StringWriter();
var xs = new System.Xml.Serialization.XmlSerializer(typeof(RSAParameters));
xs.Serialize(sw, pubKey);
publicKey = sw.ToString();
}
}
}
這個類將加密的用戶名和密碼字符串(標記)。在登錄方法中,您檢查用戶名和密碼,並根據用戶名和密碼生成令牌並返回此令牌。 在任何進一步的請求中,客戶端必須在請求頭中附加這個令牌。
爲了檢查進一步的請求,您可以使用自定義驗證屬性:
public interface IApiAuthenticationProvider
{
bool IsValid(string username, string password);
}
public static class ApiAuthenticationEncrypter
{
public static string Encrypt(string username, string password)
{
return ApiRSA.Encrypt(/*join username and password*/);
}
public static void Decrypt(string token, out string username, out string password)
{
var usernameAndPass = ApiRSA.Decrypt(token).Split(/*split username and password*/);
username = usernameAndPass[0];
password = usernameAndPass[1];
}
}
public class ApiAuthenticationAttribute : ActionFilterAttribute
{
private IApiAuthenticationProvider AuthenticationProvider { get; set; }
public ApiAuthenticationAttribute(Type apiAuthenticationType)
{
Debug.Assert(typeof(IApiAuthenticationProvider).IsAssignableFrom(apiAuthenticationType));
AuthenticationProvider = (IApiAuthenticationProvider) Activator.CreateInstance(apiAuthenticationType);
}
public override void OnActionExecuting(HttpActionContext actionContext)
{
Debug.Assert(AuthenticationProvider != null);
Object httpContextBase;
bool isValid = actionContext.Request.Properties.TryGetValue("MS_HttpContext", out httpContextBase);
bool isLocal = isValid && ((HttpContextBase)httpContextBase).Request.IsLocal;
if (isLocal)
{
base.OnActionExecuting(actionContext);
return;
}
//// == Only Https request ==
//if (!String.Equals(actionContext.Request.RequestUri.Scheme, "https", StringComparison.OrdinalIgnoreCase))
//{
// actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest)
// {
// Content = new StringContent("HTTPS Required")
// };
// return;
//}
// == Try to get Token ==
string token;
try
{
token = actionContext.Request.Headers.GetValues("AuthenticationToken").First();
}
catch (Exception)
{
actionContext.Response = new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new StringContent("AuthenticationToken not found"),
};
return;
}
// == Validate using validator provider ==
try
{
string username;
string password;
ApiAuthenticationEncrypter.Decrypt(token, out username, out password);
if (AuthenticationProvider.IsValid(username, password))
base.OnActionExecuting(actionContext);
else
throw new Exception();
}
catch (Exception)
{
actionContext.Response = new HttpResponseMessage(HttpStatusCode.Forbidden)
{
Content = new StringContent("Invalid UserName or Password")
};
return;
}
}
}
而且通過一個具體類型的IApiAuthenticationProvider
使用這個屬性:
[ApiAuthentication(typeof (Concrete Type of IApiAuthenticationProvider))]
public class SomeController: ApiController
讀Here
來源
2013-12-17 08:33:35
MRB
'[Authorize]'不適合你嗎? – Tobberoth