/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* This software is subject to the Microsoft Public License (Ms-PL).
* A copy of the license can be found in the license.htm file included
* in this distribution.
*
* You must not remove this notice, or any other, from this software.
*
* ***************************************************************************/
namespace System.Web.Mvc{
using System;
using System.Security.Cryptography;
using System.Security.Principal;
using System.Text;
internal sealed class AntiForgeryData {
private const string AntiForgeryTokenFieldName = "__RequestVerificationToken";
private const int TokenLength = 128 / 8;
private readonly static RNGCryptoServiceProvider _prng = new RNGCryptoServiceProvider();
private DateTime _creationDate = DateTime.UtcNow;
private string _salt;
private string _username;
private string _value;
public AntiForgeryData() {
}
// copy constructor
public AntiForgeryData(AntiForgeryData token) {
if (token == null) {
throw new ArgumentNullException("token");
}
CreationDate = token.CreationDate;
Salt = token.Salt;
Username = token.Username;
Value = token.Value;
}
public DateTime CreationDate {
get {
return _creationDate;
}
set {
_creationDate = value;
}
}
public string Salt {
get {
return _salt ?? String.Empty;
}
set {
_salt = value;
}
}
public string Username {
get {
return _username ?? String.Empty;
}
set {
_username = value;
}
}
public string Value {
get {
return _value ?? String.Empty;
}
set {
_value = value;
}
}
private static string Base64EncodeForCookieName(string s) {
byte[] rawBytes = Encoding.UTF8.GetBytes(s);
string base64String = Convert.ToBase64String(rawBytes);
// replace base64-specific characters with characters that are safe for a cookie name
return base64String.Replace('+', '.').Replace('/', '-').Replace('=', '_');
}
private static string GenerateRandomTokenString() {
byte[] tokenBytes = new byte[TokenLength];
_prng.GetBytes(tokenBytes);
string token = Convert.ToBase64String(tokenBytes);
return token;
}
// If the app path is provided, we're generating a cookie name rather than a field name, and the cookie names should
// be unique so that a development server cookie and an IIS cookie - both running on localhost - don't stomp on
// each other.
internal static string GetAntiForgeryTokenName(string appPath) {
if (String.IsNullOrEmpty(appPath)) {
return AntiForgeryTokenFieldName;
}
else {
return AntiForgeryTokenFieldName + "_" + Base64EncodeForCookieName(appPath);
}
}
internal static string GetUsername(IPrincipal user) {
if (user != null) {
IIdentity identity = user.Identity;
if (identity != null && identity.IsAuthenticated) {
return identity.Name;
}
}
return String.Empty;
}
public static AntiForgeryData NewToken() {
string tokenString = GenerateRandomTokenString();
return new AntiForgeryData() {
Value = tokenString
};
}
}
}
|