Building an API

polaris · · 580 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I am pretty new to API building. </p> <p>I want to build an API to a web app of mine, what approach is the best one? using JWT over normal sessions key exchange (exchange the username/password and generate a token valid for some time)?</p> <p>Edit: I have written a small book on writing webapps with Go, <a href="https://github.com/thewhitetulip/web-dev-golang-anti-textbook/">https://github.com/thewhitetulip/web-dev-golang-anti-textbook/</a></p> <p>Have 0 experience in API development though.</p> <hr/>**评论:**<br/><br/>dbot77: <pre><p>I have been using <a href="https://github.com/gin-gonic/gin" rel="nofollow">gin</a> lately and really like the routing/middleware system that it provides. </p> <p>Using JWT is a good idea because you don&#39;t have to store the session state on the server.</p></pre>thewhitetulip: <pre><p>thank you! What are your thoughts about not using JWT but using a custom implementation? like generating a UUID by some logic based on the username and password sent by the user, if I don&#39;t want to use any third party library. Is there any specific advantage that JWT provides over a custom simple implementation?</p></pre>dbot77: <pre><p>JWT&#39;s are nice because they provide:</p> <ul> <li>built-in expiration time</li> <li>custom data in payload that can&#39;t be changed (if somebody modifies the payload it invalidates token)</li> <li>is standardized and has good packages in many languages</li> </ul></pre>thewhitetulip: <pre><p>In the API, do we send POST requests right? to get the token and send receive the data, is there something wrong with the assumption I have in the comment in SeerUD&#39;s comment?</p></pre>tmornini: <pre><p>You probably send a POST over SSL using Basic Authentication for username/password or a secret token, and return a JWT as the Authorization header, so the client can then use the same Authorization header for future requests.</p> <p>For the actual API calls that manipulate data and processes, then you should use the HTTP method described (here.)[<a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html" rel="nofollow">http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html</a>]</p> <p>Read that a few times. Don&#39;t rush it -- and don&#39;t consider yourself finished until it all makes sense. :-)</p></pre>thewhitetulip: <pre><p>Thank you! For the API I&#39;ll make sure I use the correct method :)</p></pre>tinygopher: <pre><p>Hey there. Other newb here. Built something for the gopher gala earlier this year. It is by no means good or production ready but it may give you an idea or a direction to follow. It connects to postgres, uses JWT, password hashing, and has some basic sql queries. I am actually gonna start working on it again now so it will get better I hope. :) But feel free to take a look: <a href="https://github.com/jebrial/learnlink" rel="nofollow">https://github.com/jebrial/learnlink</a></p> <p>edit: I forgot to mention I am using GIN right now but I may look into rolling my own with fasthttp. edit2: I like GIN and I would only be doing the roll my own for learning purposes although I hear fasthttp is mad fast.</p></pre>thewhitetulip: <pre><p>thank you!</p></pre>tinygopher: <pre><p>No problem!</p></pre>SeerUD: <pre><p>This is quite a broad question to answer in a single thread. Are there any parts in particular you have questions about?</p> <p>As a sweeping set of statements; you can get very far just using the standard library of Go to make a RESTful API, keep things simple, look at other examples. Start adding in dependencies only when you need them, if the need is great enough.</p> <p>You can handle authentication many different ways, perhaps start with the simplest solution you can using some kind of authentication middleware and go from there?</p></pre>thewhitetulip: <pre><p>Edit: If you downvote, please advise me on what&#39;s wrong in the comment. Just downvoting doesn&#39;t help at all</p> <p>Okay, so narrowing down:</p> <ol> <li>I have a todo list manager github.com/thewhitetulip/Tasks</li> <li>I want to be able to add/delete/modify tasks via a command line app, which&#39;ll use this API also if I made an android app later it&#39;ll work with it.</li> <li>I have used middleware so am comfortable using it.</li> </ol> <p>I understand that is should work in this way</p> <pre><code>/api/gettoken POST username,password -&gt; server client &lt;- security token /api/add/task POST token=token name=dummy title=dummy due_date=tomorrow </code></pre> <p>I know how to route a URL, this isn&#39;t an issue. My problem comes in the token handling part. How do I handle the token? Let&#39;s say I first </p> <p>I want to build the bot in Go itself.</p> <pre><code>//my bot token, err := http.POST(/api/gettoken) username &amp; password sent err := http.POST({title:&#39;hello&#39;, content:&#39;world&#39;}) //ignoring error //---server-- func GetToken(username, password string) token string{ username := r.Form.Get(&#34;name&#34;) pwd := r.Form.Get(&#34;password&#34;) if IsValidUser(username, pwd) { return generateToken() } } </code></pre> <p>This works wonders in normal forms and over http, how do we do this in the API? I know this that we send JSON documents over API, that won&#39;t be an issue</p> <ol> <li>How to manager sessions, do we take a POST request for the username/password? how to generate the unique token?</li> <li>If we really do use POST then writing the middleware for the authentication is really simple and would solve all my problems. As I&#39;ll get the token via a POST statement, I&#39;ll read it on the server side, and call my db functions which I invoke on the same data when I get them via forms.</li> </ol></pre>Sythe2o0: <pre><p>So because you&#39;re asking, the reason I&#39;ve downvoted is in response to your requests to not downvote-- it&#39;s in bad taste.</p></pre>thewhitetulip: <pre><p>Do you understand the meaning of &#34;If you downvote, please advise me on what&#39;s wrong in the comment. Just downvoting doesn&#39;t help at all&#34;</p> <p>Does it say that &#34;Hey don&#39;t downvote me?&#34; </p> <p>If you have nothing +ve to contribute then sit in the shadows rather than being a sadist and hindering someone else&#39;s learning experience.</p></pre>Sythe2o0: <pre><p>My comment was more in the context of your op.</p></pre>thewhitetulip: <pre><p>Removed it from the op.</p> <p>I am amazed at how negative people can be. Thank you for giving me a practical experience. In future I won&#39;t be as surprised at the sadism certain people show and will make sure I ignore the downvotes.</p></pre>umpc: <pre><p>Since November, I&#39;ve been using Go to build my first web API that authenticates against a RDBMS, returns a JWT, and then allows for &#39;stateless&#39; interaction for several hours.</p> <p>Some stuff that I see others do wrong that you should look out for if you use them: Add an expiration time to your tokens. Otherwise, you&#39;ll have to change your pub/priv signing key in order to invalidate tokens.</p> <p>There are apps on the Google Play Store right now that use a single token for &#39;login-free&#39; authentication. Anyone can reverse engineer these apps and then use this whenever they would like, for as long as they would like, and appear to come from their app with very little spoofing.</p> <p>The big one to avoid is that the JWT spec has a vulnerability, but it&#39;s easy to avoid: <a href="https://github.com/dgrijalva/jwt-go/issues/59#issuecomment-88567525" rel="nofollow">https://github.com/dgrijalva/jwt-go/issues/59#issuecomment-88567525</a></p></pre>thewhitetulip: <pre><p>I have read of that vulnerability. </p> <p>One questions i&#39;d like to ask you is what should be the expiration time? A week? a few weeks? or does it depend, if so, on what factors?</p> <p>Also it is beyond me how people can create login-free applications, it is utter nonsense to be stated in blunt terms, mobile phones aren&#39;t tied up to a place, they are placed in pockets and handed over to the user with the data in the phone :-D of course people are going to reverse engineer it!</p></pre>umpc: <pre><p>I simply suggest that it have some sort of expiration time that suits your use case in order to prevent &#39;master key&#39; access tokens from existing.</p> <p>It&#39;s simply an opinion of mine after being baffled by how easy it is to find these types of access tokens in decompiled mobile apps. Mine expire after 6 hours for &#39;trusted&#39; users, and 1 hour for free mobile app users, though the latter policy might be excessive for most cases.</p> <blockquote> <p>Also it is beyond me how people can create login-free applications,</p> </blockquote> <p>It&#39;s easy. Most developers of login-free, data-driven apps, just assume that the majority of users will never try to find this built-in key. The app just uses one key for login-free access that is ether shipped unobscured in the source code to the app stores (most likely), or is obscured (less likely).</p> <p>EDIT: I think from your other post that you get this, but for others who see this: If it travels over a network to the device, it&#39;s now compromised. So design around that, use HTTPS with HSTS, and don&#39;t ship keys that you can help to not keep in the open.</p></pre>thewhitetulip: <pre><p>Thank you for the detailed comment!</p> <p>Few months back at work I had taken part in building an app using third party API via Java, we used to send a request for a token by sending a username/password and get the token</p> <p>which we used for future requests.</p> <p>If we had done this, then we won&#39;t have people being able to generate tokens at whim, correct? If I have my keys in the app source code, then yes, certain people can and will get through to pick up the key and screw up everything..</p> <p>What approach do you suggest to generate auth tokens? sending username/password to the server in exchange a token or some other way to generate token?</p></pre>umpc: <pre><blockquote> <p>we used to send a request for a token by sending a username/password and get the token</p> <p>If we had done this, then we won&#39;t have people being able to generate tokens at whim, correct?</p> </blockquote> <p>If I understand you correctly, you worked on an app that sends a username and password and then receives an access token of some form in response.</p> <p>With JWT, as you probably know, the app on the server generates the token using its own private and public key, typically during login.</p> <p>I think my last EDIT is a bit confusing about this: I say compromised as in the end-user can view and replicate it. As in, do not make an app without a built-in login-free token that downloads one from a server, thinking you&#39;ve outsmarted people.</p> <p>Sending a login/pass + some form of captcha if absolutely needed and receiving a <del>one-time-use</del> access token is best practice.</p> <p>EDIT: To be even more clear, I mean one-time-use as in the time from when it&#39;s issued to when it&#39;s considered expired and invalid.</p></pre>thewhitetulip: <pre><p>yes, that was the app I had worked on.</p> <p>Okay, so If i have understood your points correctly</p> <pre><code>username, password -&gt; send to server to get a token client &lt;- server (sends token) client -&gt; makes requests based on the token, server will check if token is expired or not before serving. </code></pre></pre>umpc: <pre><p>Exactly. ;)</p></pre>thewhitetulip: <pre><p>Thank you very much! I built the API functions yesterday, now have to take care of authentication.</p> <p>Do you have any tips on performance or other aspects of API?</p></pre>Floooof: <pre><p>Take a look at <a href="https://auth0.com" rel="nofollow">Auth0</a> for the JWT part of this. Alternatively, you can implement your own authentication using a database and/or social login, then issue JWTs using the resources you find at jwt.io. For actual API serving, you might try a <a href="https://github.com/derekdowling/jsh-api" rel="nofollow">go implementation of json-api built as a thin layer on top of goji</a>. Adding JWT middleware to goji is pretty painless, too.</p></pre>nocpu: <pre><p>I cant stress enough how good <a href="https://www.amazon.co.uk/Web-Development-Go-Building-Scalable/dp/1484210530/ref=sr_1_1?s=books&amp;ie=UTF8&amp;qid=1463652928&amp;sr=1-1" rel="nofollow">this</a> book is. It teaches from first principles rather than just saying &#34;lets implement X framework&#34;. The book does assume a certain knowledge about Go already and only has a small section on the basics.</p></pre>thewhitetulip: <pre><p>Even I wrote a book! <a href="https://github.com/thewhitetulip/web-dev-golang-anti-textbook/" rel="nofollow">https://github.com/thewhitetulip/web-dev-golang-anti-textbook/</a> Stresses on principles and real examples ;-)</p> <p>I read amazon reviews and found them to be somewhat fake, almost all reviews focus on chapter 9 alone. Apparently the book doesn&#39;t have anything other than chapter 9 i.e. the RESTful API chapter</p></pre>nocpu: <pre><p>Haha, typical programmers just wanting to code. Chapter 9 is where it gets meaty, so I understand the reviews. I will be sure to read your book, free is always best!!</p></pre>thewhitetulip: <pre><p>hahahaha. My book doesn&#39;t contain anything related to REST, but this sunday I&#39;ll make sure to learn and write it using a real example</p> <p>Much of the book is based on my learnings I got while building <a href="https://github.com/thewhitetulip/Tasks" rel="nofollow">https://github.com/thewhitetulip/Tasks</a></p> <p>There aren&#39;t many open source books which teach the concepts using a real example, much of them are either too high level overview or give too simple example and then expect the user to suddenly understand everything on their own without giving a proper code example</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

580 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传