@Html. antiforgerytoken () Source code analysis, form anti-counterfeiting code generation

Source: Internet
Author: User
Tags httpcontext

Source code from MVC4
@Html. antiforgerytoken () Source code Analysis

Public mvchtmlstring AntiForgeryToken () {    return new mvchtmlstring (antiforgery.gethtml (). ToString ());}

Antiforgery from System.Web.Helpers.AntiForgery

public static htmlstring gethtml () {    if (httpcontext.current = = Null)    {        throw new ArgumentException ( webpageresources.httpcontextunavailable);    }    Tagbuilder forminputelement = Antiforgery._worker. Getforminputelement (new httpcontextwrapper (httpcontext.current));    return forminputelement.tohtmlstring (tagrendermode.selfclosing);}

Find out the creation of _worker
private static readonly Antiforgeryworker _worker = Antiforgery.createsingletonantiforgeryworker ();

Discover Iantiforgerytokenserializer from Antiforgerytokenserializer
And find the instance object with so interface, start to see the specific code implementation

private static Antiforgeryworker Createsingletonantiforgeryworker () {    Icryptosystem cryptosystem = machinekey45cryptosystem.instance;    if (cryptosystem = = Null)    {        cryptosystem = new Machinekey40cryptosystem ();    }    Iantiforgeryconfig config = new Antiforgeryconfigwrapper ();    Iantiforgerytokenserializer serializer = new Antiforgerytokenserializer (cryptosystem);    Itokenstore tokenstore = new Antiforgerytokenstore (config, serializer);    Iclaimuidextractor claimuidextractor = new Claimuidextractor (config, claimsidentityconverter.default);    Itokenvalidator validator = new Tokenvalidator (config, claimuidextractor);    return new Antiforgeryworker (serializer, config, tokenstore, validator);}

_worker's getforminputelement, found that value is _serializer. Serialize is serialized out, the Antiforgerytokenserializer object is then viewed

Public Tagbuilder getforminputelement (httpcontextbase Httpcontext) {this    . Checksslconfig (httpcontext);    AntiForgeryToken Cookietokennothrow = This. Getcookietokennothrow (httpcontext);    AntiForgeryToken antiforgerytoken;    AntiForgeryToken token;    This. Gettokens (httpcontext, cookietokennothrow, out antiforgerytoken, out token);    If (antiforgerytoken! = Null)    {        this._tokenstore.savecookietoken (httpcontext, antiforgerytoken);    }    Tagbuilder tagbuilder = new Tagbuilder ("input");    tagbuilder.attributes["type"] = "hidden";    tagbuilder.attributes["name"] = This._config. formfieldname;    tagbuilder.attributes["value"] = This._serializer. Serialize (token);    Return tagbuilder;}

Find the Serialize function of the Antiforgerytokenserializer object

 public string Serialize (antiforgerytoken token) {string result; Using (memorystream MemoryStream = new MemoryStream ()) {using (BinaryWriter BinaryWriter = new BinaryWriter (mem            Orystream)) {binarywriter.write (1); BinaryWriter.Write (token.            Securitytoken.getdata ()); BinaryWriter.Write (token.            issessiontoken); If (!token. Issessiontoken) {if (token.                    Claimuid = Null) {binarywriter.write (true); BinaryWriter.Write (token.                Claimuid.getdata ());                    } else {binarywriter.write (false); BinaryWriter.Write (token.                Username); } binarywriter.write (token.            additionaldata);            } Binarywriter.flush ();        result = This._cryptosystem.protect (memorystream.toarray ()); }} return result;} 

/key Serialization functions
Generate Doubts Token. Securitytoken.getdata (), Where did this data come from?
Token. Issessiontoken This is bool, see the name to know is used to determine whether to generate the association session token


Return to view AntiForgeryToken this class
//
found that this section of the Getforminputelement function was created so

AntiForgeryToken token;
This. Gettokens (httpcontext, cookietokennothrow, out antiforgerytoken, out token);


View _worker known instances through the top
Itokenstore tokenstore = new Antiforgerytokenstore (config, serializer);
Find the

private void Gettokens (httpcontextbase httpcontext, antiforgerytoken oldcookietoken, out AntiForgeryToken newcookietoken, out AntiForgeryToken formtoken) {    newcookietoken = null;    If (!this._validator. Iscookietokenvalid (oldcookietoken))    {        antiforgerytoken antiforgerytoken;        Newcookietoken = (antiforgerytoken = This._validator. Generatecookietoken ());        Oldcookietoken = antiforgerytoken;    }    Formtoken = This._validator. Generateformtoken (httpcontext, antiforgeryworker.extractidentity (httpcontext), oldcookietoken);}

Keep Looking.

Public AntiForgeryToken generateformtoken (httpcontextbase httpcontext, IIdentity identity, AntiForgeryToken Cookietoken) {antiforgerytoken antiforgerytoken = new AntiForgeryToken {securitytoken = cookietoken.security    Token, Issessiontoken = false//the original default is false, temporarily consider the default is not to use the session};    BOOL flag = false; If (identity! = null && Identity. Isauthenticated) {if (!this._config.        Suppressidentityheuristicchecks) {flag = true;        } antiforgerytoken.claimuid = This._claimuidextractor.extractclaimuid (identity); if (antiforgerytoken.claimuid = = Null) {antiforgerytoken.username = Identity.        Name; }} if (this._config. Additionaldataprovider = Null) {antiforgerytoken.additionaldata = this._config.    Additionaldataprovider.getadditionaldata (httpcontext); } If (flag && string. IsNullOrEmpty (antiforgerytoken.username) && Antiforgerytoken.claimuid = = NULL && sTring. IsNullOrEmpty (antiforgerytoken.additionaldata)) {throw New InvalidOperationException (string.        Format (cultureinfo.currentculture, webpageresources.tokenvalidator_authenticateduserwithoutusername, New object[] {identity.    GetType ()})); } return antiforgerytoken;}

The creation of tokens is clear after such a look.


Then look at token tokens. SecurityToken this property

Public Binaryblob securitytoken{    Get    {        if (this._securitytoken = = Null)        {            this._securitytoken = New Binaryblob (128);//find Default is 128, object is Binaryblob        }        return this._securitytoken;    }    Set    {        This._securitytoken = value;    }}

View the Binaryblob constructor, and a Generatenewtoken function appears

Public Binaryblob (int. bitlength): this (bitlength, binaryblob.generatenewtoken (bitlength)) {}

Generatenewtoken Source

private static byte[] Generatenewtoken (int bitlength) {    byte[] array = new byte[bitlength/8];    Binaryblob._prng. GetBytes (array);    Return array;}

damn, There's An unknown thing That's appearing, _prng
private static readonly RNGCryptoServiceProvider _prng = new RNGCryptoServiceProvider ();

[securitysafecritical]public override void GetBytes (byte[] Data) {    if (data = = Null)    {        throw new ArgumentNullException ("data");    }    Rngcryptoserviceprovider.getbytes (this.m_safeprovhandle, data, Data. Length);} [securitycritical, suppressunmanagedcodesecurity] [DllImport ("QCall", CharSet = charset.unicode)]private static extern void GetBytes (safeprovhandle hprov, byte[] randombytes, int count);

Bing is now a RNGCryptoServiceProvider class (bing check MSDN is especially Handy)
Https://msdn.microsoft.com/zh-cn/library/system.security.cryptography.rngcryptoserviceprovider (v=vs.110). aspx
Http://www.cnblogs.com/izanami/archive/2011/04/20/2022173.html
The original RNGCryptoServiceProvider GetBytes with a cryptographically strong random value sequence to populate the byte array, the final random data generation!

Now the serialized part has been solved some binarywriter.write (1); binarywriter.write (token. Securitytoken.getdata ());//data is clear, a section of a cryptographically strong random value array BinaryWriter.Write (token. Issessiontoken)//bool determine whether to use sessionif (!token. Issessiontoken) {    If (token. Claimuid = Null)    {        binarywriter.write (true);        BinaryWriter.Write (token. Claimuid.getdata ());//is also a binaryblob    }    else    {        binarywriter.write (false);        BinaryWriter.Write (token. Username);    }    BinaryWriter.Write (token. additionaldata);} Binarywriter.flush (); result = This._cryptosystem.protect (memorystream.toarray ());


Continue to untie Claimuid.
In the above generateformtoken found such a section
Antiforgerytoken.claimuid = This._claimuidextractor.extractclaimuid (identity);
The place where _claimuidextractor was created is Claimuidextractor.
Discover source

Public Binaryblob extractclaimuid (IIdentity identity) {    if (identity = = NULL | |!identity. isauthenticated | | This._config. Suppressidentityheuristicchecks)    {        return null;    }    Claimsidentity claimsidentity = This._claimsidentityconverter.tryconvert (identity);    if (claimsidentity = = Null)    {        return null;    }    string[] uniqueidentifierparameters = claimuidextractor.getuniqueidentifierparameters (claimsIdentity, this._config . uniqueclaimtypeidentifier);    byte[] data = cryptoutil.computesha256 (uniqueidentifierparameters);    return new Binaryblob (n, data);}
public static byte[] ComputeSHA256 (ilist<string> parameters) {    byte[] result;    Using (memorystream MemoryStream = new MemoryStream ())    {        using (BinaryWriter BinaryWriter = new BinaryWriter ( Memorystream)        {            foreach (string parameters)            {                binarywriter.write (current);            }            Binarywriter.flush ();            Using (SHA256 SHA = cryptoutil._sha256factory ())            {                byte[] array = Sha.computehash (memorystream.getbuffer (), 0, checked ((int) memorystream.length));                result = array;}}    }    Return result;}

Discovery is a hash computed value of SHA256
And then the Additionaldata.

public string additionaldata{    get    {        return this._additionaldata?? string. Empty;    }    Set    {        this._additionaldata = value;    }}

The last is the sentence result = This._cryptosystem.protect (memorystream.toarray ());
Machinekey40cryptosystem:icryptosystem

public string Protect (byte[] data) {    byte[] array = new Byte[data. Length + 4];    Buffer.blockcopy (data, 0, array, 4, Data. Length);    array[0] = 133;    array[1] = 135;    array[2] = 242;    array[3] = 102;    String hex = This._encoder (array, machinekeyprotection.all);    return machinekey40cryptosystem.hextobase64 (hex);} Internal static string HexToBase64 (string hex) {    int num = Hex. length/2;    byte[] array = new byte[num];    for (int i = 0; i < num; i++)    {        array[i] = (byte) ((machinekey40cryptosystem.hexvalue (hex[i * 2) << 4) + Machinekey40cryptosystem.hexvalue (hex[i * 2 + 1]));    }    return Httpserverutility.urltokenencode (array);}

Convert randomly generated data into 16 binary strings
This is the end of the Encryption.

and finally the corresponding Decryption.

Public AntiForgeryToken deserialize (string serializedtoken) {try {using (memorystream MemoryStream = new Mem Orystream (this._cryptosystem.unprotect (serializedtoken))) {using (binaryreader binaryreader = new Binar Yreader (memorystream)) {antiforgerytoken AntiForgeryToken = antiforgerytokenserializer.deserial                Izeimpl (binaryreader);                If (antiforgerytoken! = Null) {return antiforgerytoken; }}}} catch {} throw httpantiforgeryexception.createdeserializationfailedexception ();} private static AntiForgeryToken Deserializeimpl (binaryreader reader) {byte b = reader.    ReadByte ();//reads the next byte from the current stream and increases the current position of the stream by 1 Bytes.    If (b! = 1)//corresponds to the encrypted BinaryWriter.Write (1);    {return null;    }//according to the fragment size of the encryption time corresponding decryption AntiForgeryToken AntiForgeryToken = new AntiForgeryToken (); byte[] data = Reader.    Readbytes (16); Antiforgerytoken.securitytoken = NEW Binaryblob (+, data); Antiforgerytoken.issessiontoken = Reader.    Readboolean (); If (!antiforgerytoken.issessiontoken) {bool flag = Reader.        Readboolean (); If (flag) {byte[] data2 = reader.            Readbytes (32);        Antiforgerytoken.claimuid = new Binaryblob (data2); } Else {antiforgerytoken.username = Reader.        ReadString (); } Antiforgerytoken.additionaldata = Reader.    ReadString (); } If (reader.    Basestream.readbyte ()! =-1) {return null; } return antiforgerytoken;}

Article reproduced http://www.cnblogs.com/RainbowInTheSky/p/5565248.html

@Html. antiforgerytoken () Source code analysis, form anti-counterfeiting code generation

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.