Original address: http://www.cnblogs.com/hubro/p/6248353.html
In the proliferation of all kinds of mobile phone app now, behind the same flooding API in support, which is a mixed-up, direct bare-Ben Web API a large number of existence, security is excellent
In the past when the Web API concept is not very popular, all adopt self-defined interface and structure, for the interface of public access, the professional point will do the security authentication, data signing and so on
But now, anyone can use the Web API to evaluate the interface, security has been left aside, especially to outsource the small company's app projects, 80% have security vulnerabilities (interview for most of the year the conclusion of the app development)
Special before the new Year, finishing the use of the solution, this solution
- Data security issues
- Standard message structure
- Interface Test Program
- Interface Document representation
Body
Data
For an interface, the returned contents are returned in addition to the business data, and this state is available on each interface
So the data format will be defined as:
Data header (Description data information)
-----------------------------------
Data body (Specific data)
This article defines the structure as
<summary>///processing results/// </summary> public class Dealresult { //<summary> /// processing results// </summary> public bool result { get; Set; } <summary>///News/// </summary> public string message { get; Set; } <summary>///Related data/// </summary> Public Object data { get; Set; } }
All interfaces return This object, describe the state of the request, and the corresponding data, and the server returns the processing result and corresponding data according to the actual situation.
Data security
Open-mode interface security There is no need to say, the solution for encryption, or data signature verification, the present scheme for data signing
As with the returned data, the data format submitted to the server is also uniformly agreed to define a data header base class
<summary>//// parameter base class/// </summary> [Serializable] public class Paramebase { String time = DateTime.Now.ToString ("Yyyy-mm-dd hh:mm:ss"); <summary>/// time format YYYY-MM-DD hh:mm:ss/// </summary> public string times { get< c12/>{ return time; } Set {Time = value; } } <summary>// Source website = 1, IOS = 2,android = 3, = 4/// </summary> public int sourcefrom< c25/>{ get; Set; } <summary>//sign//// </summary> public string Token { get; Set; } }
A login object is represented as
<summary>///Login/// </summary> public class Login:paramebase { //<summary >///user name/// </summary> public string name { get; Set; } <summary>//password/// </summary> public string Password { get; Set; } }
Data signature represented as (key later)
Token=md5 (attribute value 1+ value 2....+KEY)
By this object represented as MD5 (name+password+source+time+KEY)
If it is a get parameter, it is calculated by the parameter name, and the arguments passed are accompanied by the Source,time,token
Key mechanism
Some like to put the key on the client, or a fixed key, obviously have a security problem, the solution is to dynamically obtain
This means that when you design an interface, there is an interface that is called first, so that the server returns the key, and then there is the concept of login
Process is expressed as
Log in > Return user information and keys = = Store user information and key = + Use Key to invoke other interfaces
This way, only the login and the server will know their own keys.
In summary, the data structure is expressed as
Client submission structure is paramebase (with signature information)
Service-side return structure is Dealresult
Login mechanism
As with Web requests, how do you know that multiple invocations are the same person, which is in the form of a cookie, which returns a cookie on the server after login, and then brings this cookie when requested by the client.
The server needs to store this cookie ID, and all authentication processing will be based on this identity to determine the user
With the above foundation, enter the project stage
WEB API Project
In fact, what type of project is OK, but the Web API facilitates object structure serialization and parameter
The Default Web API routing resuful form, no controller method, can only be defined by method, very inconvenient, changed to the form of a controller, so that you can use the method name to access the
Change the routing configuration to
12345 |
config.Routes.MapHttpRoute(
name:
"DefaultApi"
,
routeTemplate:
"api/{controller}/{action}/{id}"
,
//加上路由ACTION参数
defaults:
new
{ id = RouteParameter.Optional }
);
|
In this article, the data is divided into requests and returns, to log back the user information as an example, log on as the request, the user information is returned, the sample object structure is
User objects
/// <summary> ///Login Return User/// </summary> Public classUser {/// <summary> ///User Number/// </summary> Public intId {Get; Set; } /// <summary> ///name/// </summary> Public stringName {Get; Set; } /// <summary> ///key for this login/// </summary> Public stringKey {Get; Set; } /// <summary> ///credentials for the registration of the funds/// </summary> Public stringVoucher {Get; Set; } }
Request method
Here only uses the Get,post two way, according to the actual situation definition, the Controller method must be marked, otherwise the routing bug will appear
Defining Login Methods
/// <summary> ///Login/// </summary> /// <param name= "Parame" ></param> /// <returns>User</returns>[HttpPost] [anonymoussign] Publicdealresult Login ([frombody] login parame) {if(Parame. Password! ="123") { returnDealresult (false,"The password is not correct"); } stringKey2 =System.Guid.NewGuid (). ToString (); stringVoucher =System.Guid.NewGuid (). ToString (); varuser =NewUser () {Name = Parame. Name, Id =1, Key = key2, Voucher =voucher}; varTimediff = (Datetime.now-convert.todatetime (parame. Time)). TotalSeconds;//Save the client and service-side time differenceloginstatuscontext.setloginstatus (voucher, user. Id, Key2, Timediff); CoreHelper.CookieHelper.AddCookies ("User", voucher);//Deposit Cookies returnDealresult (true,"", user); }
Here you can see, created two GUIDs, one for the user credentials, one for the user key, put the user information back, and call Loginstatuscontext.setloginstatus to save the login information
Anonymoussign annotations are also used, and this method uses the default signature Setting.defaultkey
Define access information methods
/// <summary> ///Basic Information/// </summary> /// <param name= "name" >Parameter name</param> /// <returns>User</returns>[HttpGet] PublicDealresult Getbasicinfo (stringname) { varuser =NewUser () {name = name, Id =Currentuserid}; returnDealresult (true,string. Empty, user); }
Example controller full definition
/// <summary> ///Account Operations/// </summary>[Signcheckattribute] Public classAccountcontroller:basecontroller {/// <summary> ///Login/// </summary> /// <param name= "Parame" ></param> /// <returns>User</returns>[HttpPost] [anonymoussign] Publicdealresult Login ([frombody] login parame) {if(Parame. Password! ="123") { returnDealresult (false,"The password is not correct"); } stringKey2 =System.Guid.NewGuid (). ToString (); stringVoucher =System.Guid.NewGuid (). ToString (); varuser =NewUser () {Name = Parame. Name, Id =1, Key = key2, Voucher =voucher}; varTimediff = (Datetime.now-convert.todatetime (parame. Time)). TotalSeconds;//Save the client and service-side time differenceloginstatuscontext.setloginstatus (voucher, user. Id, Key2, Timediff); CoreHelper.CookieHelper.AddCookies ("User", voucher);//Deposit Cookies returnDealresult (true,"", user); } /// <summary> ///Basic Information/// </summary> /// <param name= "name" >Parameter name</param> /// <returns>User</returns>[HttpGet] PublicDealresult Getbasicinfo (stringname) { varuser =NewUser () {name = name, Id =Currentuserid}; returnDealresult (true,string. Empty, user); } /// <summary> ///Test Exception/// </summary> /// <returns></returns>[HttpGet] PublicDealresult testexception () {intA =0; varb =Ten/A; returnDealresult (true); } }
This controller marks the Signcheckattribute for signature determination
Concrete implementation can see Signcheckattribute code
Signcheckattribute has been implemented in the
- Data signature Judgment
- Signature timeout judgment
- User Login Restrictions
- Signature Reuse processing (one signature can only be used once)
- Expired logon user processing (no active exit user cleanup)
Exception handling configured for uniform handling of exceptions
1 |
GlobalConfiguration.Configuration.Filters.Add( new ExceptionAttribute()); |
Testing the interface
The big kill has come, with this program released the corresponding test tools, although the Web API has an extension, but it is not able to test this scenario
Using this tool can easily call the interface according to the requirements of the scheme, in order to facilitate the parameter stitching, post and get are entered in the form of URL parameters
Test login/api/account/login
Test Get information/api/account/getbasicinfo
Test exception Handling/api/account/testexception
Call to get information in the case of not logged in
Interface documentation
Interface structure documentation has always been a headache, handwriting changes and maintenance, version is not the same trouble, automatic generation of the best, the same Web API with the extension can not represent this structure details
The big kill 2nd is here. Dynamically generate interface documentation according to code comments, document format consistent with controller
Home Controller Code implementation
Public ActionResult Index (summaryanalysis.exporttype exporttype = SummaryAnalysis.ExportType.NONE) { if ( Exporttype! = SummaryAnalysis.ExportType.NONE) { var str = summaryanalysis.load (exporttype); return File (str, "Application/octet-stream", "model_" + Exporttype + ". zip"); } else { if (string. IsNullOrEmpty (output)) { output = Summaryanalysis.load (Exporttype); } Viewbag.output = OutPut; return View ();}} }
In the development documentation that I've seen, I think it's the best form of presentation, with anchor points, quick positioning to the object structure, and consistent with the source code.
The Web API comes with document generation differences
Attach Project Source code
Http://pan.baidu.com/s/1c2rDacK
Project structure:
----------the WPF test program
----------Interface Example
Although it has nothing to do with the CRL rapid development Framework, it is also the name of the CRL, the good text to the top!
"Go" complete and secure API interface solution