この記事では、API に関する関連知識を紹介します。主に、API を設計するときに注意すべき点を紹介します。エレガントな API インターフェースを設計する方法に興味がある方は、以下を見てみましょう。
実際の作業では、サードパーティのプラットフォームを扱う必要があることが多く、サードパーティのプラットフォームの API インターフェイスに接続したり、サードパーティの API インターフェイスを提供したりすることがあります。プラットフォームの呼び出し。
そこで問題は、エレガントな API インターフェイスを設計した場合、セキュリティ、反復可能な呼び出し可能性、安定性、適切な配置などのさまざまなニーズを満たすことができるかということです。
今日はAPIインターフェースを設計する際に注意すべき点についてお話しますので、お役に立てれば幸いです。
API インターフェイス内のデータが改ざんされるのを防ぐために、多くの場合、API インターフェイスに 署名
する必要があります。
インターフェースリクエスタは、リクエストパラメータ
タイムスタンプ
key
を文字列に連結し、md5
などを渡します。アルゴリズムは前の符号を生成します。
次に、sign パラメータをリクエスト パラメータまたはリクエスト ヘッダーに追加し、API インターフェイスに渡します。
API インターフェイスのゲートウェイ サービスは、符号値を取得し、同じリクエスト パラメーターのタイムスタンプ キーを使用して文字列に結合し、同じ m5 アルゴリズムを使用して別の符号を生成し、2 つの符号値を比較します。等しい。
2 つの符号が等しい場合、それは有効なリクエストとみなされ、API インターフェイスのゲートウェイ サービスはリクエストを対応するビジネス システムに転送します。
2 つの符号が等しくない場合、API インターフェイスのゲートウェイ サービスは直接署名エラーを返します。
ここで疑問が生じます: なぜタイムスタンプを署名に追加する必要があるのでしょうか?
回答: セキュリティ上の理由から、同じリクエストが繰り返し使用されることを防ぎ、キーがクラックされない可能性を高めるために、各リクエストに 15 分などの適切な有効期限を設定する必要があります。
このようなリクエストは 15 分以内に有効ですが、15 分を超えると、API インターフェイスのゲートウェイ サービスは有効期間が終了したことを示す例外プロンプトを返します。
現在、署名の生成に使用されるキーの形式は 2 つあります。
1 つは、固定値の privateKey について両当事者が合意することです。
もう 1 つは、API インターフェイス プロバイダーが AK/SK という 2 つの値を与え、署名のキーとして SK を使用することに両当事者が同意することです。 AK インターフェイス呼び出し元は、それをヘッダーの accessKey として API インターフェイス プロバイダーに渡します。これにより、API インターフェイス プロバイダーは AK に基づいて SK を取得し、新しい sgin を生成できます。
当社の API インターフェースは、ユーザーの銀行カード番号、送金金額、ユーザー ID カードなどの非常に重要なデータを直接送信することがあります。テキストを公共のインターネットに直接公開するのは危険です。
したがって、データを暗号化する必要があります
。
現在、最も一般的に使用されている方法は、暗号化と復号化に BASE64
を使用することです。
特定のルールに従ってすべてのデータを大きな文字列に結合し、key
を追加してそれらを結合することができます。
その後、JDK1.8 以降の Base64 ツール クラスを使用して処理すると、次のような効果が得られます:
【加密前的数据】www.baidu.com 【加密后的数据】d3d3LmJhaWR1LmNvbQ==复制代码
セキュリティのために、Base64 を使用して複数回暗号化できます。
API インターフェイスの呼び出し元がパラメーターを渡すとき、本文にはパラメーター データが 1 つだけあります。これは、base64 以降の暗号化されたデータです。
APIインターフェースのゲートウェイサービスは、データデータを受信後、双方があらかじめ決めた鍵、暗号化アルゴリズム、暗号化時間などに従って復号化し、パラメータデータをデシリアライズします。
API インターフェイスのセキュリティをさらに強化し、インターフェイスの署名や暗号化が解読されるのを防ぐために、攻撃者は自分のサーバー上のインターフェイスを要求できます。 。
要件制限リクエストip
、ipホワイトリスト
を追加します。
ホワイトリスト内の IP アドレスのみが API インターフェイスを正常に要求できます。そうでない場合、アクセス許可は直接返されません。
IP ホワイトリストは API ゲートウェイ サービスに追加することもできます。
ただし、企業の内部アプリケーション サーバーの侵害を防ぐことも必要であり、この場合、API インターフェイス リクエストは内部サーバーから開始される可能性もあります。
現時点では、ModSecurity などの Web ファイアウォールを追加する必要があります。
API インターフェイスがサードパーティ プラットフォームによって呼び出される場合、これは呼び出しの頻度を制御できないことを意味します。
サードパーティ プラットフォームが API インターフェイスを呼び出すとき、同時実行性が高すぎると、API サービスが利用できなくなり、インターフェイスが直接ハングアップする可能性があります。
したがって、電流制限
は API インターフェースで行う必要があります。
電流制限方法は 3 つあります。
リクエストされた IP の電流を制限します。たとえば、同じ IP に対して、1 分以内にリクエストの総数を制限します。 API インターフェイスの回数
は 10,000 回を超えることはできません。
リクエスト インターフェイスのフローを制限します。たとえば、同じ IP の場合、1 分以内に 指定された API インターフェイス
へのリクエストの数が 2,000 回を超えることはできません。 。
リクエスト ユーザーのフローを制限します。たとえば、同じ AK/SK ユーザー
は、1 分間に API インターフェイスに対して 10,000 件以下のリクエストを行うことができます。
我们在实际工作中,可以通过nginx
,redis
或者gateway
实现限流的功能。
我们需要对API接口做参数校验
,比如:校验必填字段是否为空,校验字段类型,校验字段长度,校验枚举值等等。
这样做可以拦截一些无效的请求。
比如在新增数据时,字段长度超过了数据字段的最大长度,数据库会直接报错。
但这种异常的请求,我们完全可以在API接口的前期进行识别,没有必要走到数据库保存数据那一步,浪费系统资源。
有些金额字段,本来是正数,但如果用户传入了负数,万一接口没做校验,可能会导致一些没必要的损失。
还有些状态字段,如果不做校验,用户如果传入了系统中不存在的枚举值,就会导致保存的数据异常。
由此可见,做参数校验是非常有必要的。
在Java中校验数据使用最多的是hiberate
的Validator
框架,它里面包含了@Null、@NotEmpty、@Size、@Max、@Min等注解。
用它们校验数据非常方便。
当然有些日期字段和枚举字段,可能需要通过自定义注解的方式实现参数校验。
我之前调用过别人的API接口,正常返回数据是一种json格式,比如:
{ "code":0, "message":null, "data":[{"id":123,"name":"abc"}] },
签名错误返回的json格式:
{ "code":1001, "message":"签名错误", "data":null }
没有数据权限返回的json格式:
{ "rt":10, "errorMgt":"没有权限", "result":null }
这种是比较坑的做法,返回值中有多种不同格式的返回数据,这样会导致对接方很难理解。
出现这种情况,可能是API网关定义了一直返回值结构,业务系统定义了另外一种返回值结构。如果是网关异常,则返回网关定义的返回值结构,如果是业务系统异常,则返回业务系统的返回值结构。
但这样会导致API接口出现不同的异常时,返回不同的返回值结构,非常不利于接口的维护。
其实这个问题我们可以在设计API网关
时解决。
业务系统在出现异常时,抛出业务异常的RuntimeException,其中有个message字段定义异常信息。
所有的API接口都必须经过API网关,API网关捕获该业务异常,然后转换成统一的异常结构返回,这样能统一返回值结构。
我们的API接口需要对异常
进行统一处理。
不知道你有没有遇到过这种场景:有时候在API接口中,需要访问数据库,但表不存在,或者sql语句异常,就会直接把sql信息在API接口中直接返回。
返回值中包含了异常堆栈信息
、数据库信息
、错误代码和行数
等信息。
如果直接把这些内容暴露给第三方平台,是很危险的事情。
有些不法分子,利用接口返回值中的这些信息,有可能会进行sql注入或者直接脱库,而对我们系统造成一定的损失。
因此非常有必要对API接口中的异常做统一处理,把异常转换成这样:
{ "code":500, "message":"服务器内部错误", "data":null }
返回码code
是500
,返回信息message
是服务器内部异常
。
这样第三方平台就知道是API接口出现了内部问题,但不知道具体原因,他们可以找我们排查问题。
我们可以在内部的日志文件中,把堆栈信息、数据库信息、错误代码行数等信息,打印出来。
我们可以在gateway
中对异常进行拦截,做统一封装,然后给第三方平台的是处理后没有敏感信息的错误信息。
在第三方平台请求你的API接口时,接口的请求日志非常重要,通过它可以快速的分析和定位问题。
我们需要把API接口的请求url、请求参数、请求头、请求方式、响应数据和响应时间等,记录到日志文件中。
最好有traceId
,可以通过它串联整个请求的日志,过滤多余的日志。
当然有些时候,请求日志不光是你们公司开发人员需要查看,第三方平台的用户也需要能查看接口的请求日志。
这时就需要把日志落地到数据库,比如:mongodb
或者elastic search
,然后做一个UI页面,给第三方平台的用户开通查看权限。这样他们就能在外网查看请求日志了,他们自己也能定位一部分问题。
サードパーティ プラットフォームは、非常に短い時間内にインターフェースを複数回リクエストする可能性が非常に高くなります (例: 1 秒以内に 2 回リクエスト)。ビジネス システムにバグがあるか、インターフェイス呼び出しの再試行に失敗する可能性があるため、API インターフェイスは idempotent
である必要があります。
つまり、非常に短期間に同じパラメータを使用して API インターフェイスを複数回リクエストできるサードパーティ プラットフォームをサポートする必要があります。データベースが初めてリクエストされるときは、新しいデータが必要になります。追加されますが、2 回目のリクエスト以降はデータは追加されません。新しいデータは追加されますが、成功も返されます。
これの目的は、誤ったデータを生成することではありません。
日常の作業では、一意のインデックス
を database
に追加するか、requestId
を redis
に保存してリクエストすることができます。インターフェイスの冪等性を確保するためのパラメータ。
インターフェイスの冪等性に興味がある友人は、私の別の記事「高い同時実行性の下でインターフェイスの冪等性を確保するにはどうすればよいですか?」を読むことができます。 」にとても詳しく紹介されています。
提供されたバッチ インターフェイスでは、要求されるレコード数を制限する必要があります
。
要求されるデータが多すぎると、APIインターフェースのタイムアウト
などの問題が発生しやすくなり、API インターフェースが不安定になります。
通常、リクエストのパラメーターは最大 500 レコードをサポートすることをお勧めします。
ユーザーが 500 を超えるレコードを渡した場合、インターフェイスは直接プロンプトを表示します。
オンライン化後の不要な問題を回避するために、このパラメータを構成可能にし、事前にサードパーティ プラットフォームとネゴシエートすることをお勧めします。
オンラインにする前に、API インターフェイスで ストレス テスト
を実行し、各インターフェイスの qps
状況を把握する必要があります。 。
これにより、デプロイする必要があるサーバー ノードの数をより正確に見積もることができます。これは、API インターフェイスの安定性に重要です。
以前にも API インターフェースの電流フローを制限したことはありますが、実際に API インターフェースが制限しきい値に到達できるかどうかは疑問符であり、ストレステストを実施しない場合は大きなリスクがあります。
例: API インターフェイスは 1 秒あたり 50 リクエストのみに制限されていますが、実際の API インターフェイスは 30 リクエストしか処理できないため、API インターフェイスはそれを処理できません。
jmeter
または apache benc
を使用して、動作中の API インターフェイスでストレス テストを実行できます。
一般的な API インターフェースのロジックは同期的に処理され、リクエスト完了後すぐに結果が返されます。
しかし、API インターフェイスのビジネス ロジック、特に一部のバッチ インターフェイスは非常に複雑になる場合があり、ビジネスが同期的に処理される場合、非常に長い時間がかかります。
この場合、API インターフェースのパフォーマンスを向上させるために、非同期処理
に変更できます。
API インターフェイスでは、mq メッセージ
を送信し、成功を直接返すことができます。その後、メッセージを非同期に消費してビジネス ロジック処理を実行する専用の mq コンシューマ
が存在します。
サードパーティ プラットフォームは、2 つの方法で直接非同期処理インターフェイスを取得できます。
最初の方法は、サードパーティ プラットフォームのインターフェースを コールバック
し、API インターフェースの処理結果を通知することであり、これが多くの決済インターフェースの動作方法です。
2 番目の方法: サードパーティ プラットフォームは、ポーリング
を通じてステータスをクエリするために他の API インターフェイスを呼び出し、時々ステータスをクエリします。渡されるパラメータは前のパラメータです。 one. API インターフェースの ID コレクション。
サードパーティのプラットフォームが当社の API インターフェイスを呼び出すと、取得されるデータの一部にユーザーの携帯電話番号、銀行カード番号などの機密データが含まれる場合があります。
そのような情報が API インターフェイスを通じて外部ネットワーク上に直接保持される場合、非常に安全ではなく、ユーザーのプライバシー データの漏洩に簡単につながる可能性があります。
これには、一部のデータに対して データの感度を下げる
が必要です。
返されたデータ内のコンテンツの一部を アスタリスク
に置き換えることができます。
ユーザーの携帯電話番号は、例として、182****887
です。
このように、データが漏洩したとしても一部のみが漏洩するため、犯罪者がこのデータを入手しても無駄になります。
正直に言うと、完全な API インターフェイス ドキュメントは、通信コストを大幅に削減し、双方がインターフェイス ドッキングを行うときに相手が多くの回り道をするのを防ぐことができます。 。
インターフェイス ドキュメントには次の情報が含まれている必要があります:
インターフェイス アドレス
リクエスト メソッド (例: post または) get
リクエスト パラメーターとフィールドの概要
IP ホワイトリストを開くなどの追加手順。
インターフェイス ドキュメント内のインターフェイス名とフィールド名の命名スタイルを統一することをお勧めします。たとえば、名前には キャメル ケース識別子
を使用します。
フィールドの型と長さを統一します。たとえば、id フィールドは Long 型を使用し、長さは 20 と指定します。 status フィールドは int 型を使用し、長さは 2 などに固定されます。
統一時刻形式フィールド。たとえば、時刻には文字列型が使用され、形式は yyyy-MM-dd HH:mm:ss です。
インターフェース文書には AK/SK とドメイン名が記載されており、別途提供するよう求められています。
推奨学習: 「PHP ビデオ チュートリアル 」
以上がAPIインターフェースを設計する際には、こんなところにも注目してください!の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。