what you won't read in books about restful services

48
The thin line between RESTful and AWful Jakub Kubrynski [email protected] / @jkubrynski 1 / 48

Upload: jakub-kubrynski

Post on 25-Dec-2014

699 views

Category:

Internet


1 download

DESCRIPTION

REST is as plain as the nose on your face. However, often exploring the secrets of this pattern ends up with the positive completion of two "Hello, World" class challenges. During this lecture we will focus on common problems and ways of handling them. We will deal with the security and best practices on topics like HATEOAS or versioning.

TRANSCRIPT

Page 1: What you won't read in books about RESTful services

The thin line between RESTful and AWfulJakub Kubrynski

[email protected] / @jkubrynski 1 / 48

Page 2: What you won't read in books about RESTful services

[email protected] / @jkubrynski 2 / 48

Page 3: What you won't read in books about RESTful services

"The Code is more what you'd call guidelines than actual rules. Welcomeaboard the Black Pearl, Miss Turner"

-- Cpt. Hector Barbossa to Elizabeth Swann

RT Ben Hale

[email protected] / @jkubrynski 3 / 48

Page 4: What you won't read in books about RESTful services

Formal REST constraintsClient-Server

Stateless

Cache

Interface / Uniform Contract

Layered System

[email protected] / @jkubrynski 4 / 48

Page 5: What you won't read in books about RESTful services

Richardson maturity model

http://martinfowler.com/articles/richardsonMaturityModel.html

[email protected] / @jkubrynski 5 / 48

Page 6: What you won't read in books about RESTful services

POST vs PUT

[email protected] / @jkubrynski 6 / 48

Page 7: What you won't read in books about RESTful services

POST vs PUTPOST creates new resources

[email protected] / @jkubrynski 7 / 48

Page 8: What you won't read in books about RESTful services

POST vs PUTPOST creates new resources

PUT updates existing resources

PUT can create resource if ID is already known

[email protected] / @jkubrynski 8 / 48

Page 9: What you won't read in books about RESTful services

Maybe PATCH?no "out of the box" support

[email protected] / @jkubrynski 9 / 48

Page 10: What you won't read in books about RESTful services

Maybe PATCH?no "out of the box" support

partial update

@RequestMapping(value = "/{id}", method = PATCH)public void updateArticle(HttpServletRequest request, @PathVariable("id") String id) { Article currentArticle = repository.findOne(id);

Article updatedArticle = objectMapper.readerForUpdating(currentArticle) .readValue(request.getReader());

repository.save(updatedArticle);}

[email protected] / @jkubrynski 10 / 48

Page 11: What you won't read in books about RESTful services

Cachingbe aware - especially IE caches aggressively

[email protected] / @jkubrynski 11 / 48

Page 12: What you won't read in books about RESTful services

Cachingbe aware - especially IE caches aggressively

disable caching

@Configurationpublic class RestConfig extends WebMvcConfigurerAdapter {

@Override public void addInterceptors(InterceptorRegistry registry) { WebContentInterceptor webContentInterceptor = new WebContentInterceptor(); webContentInterceptor.setCacheSeconds(0); registry.addInterceptor(webContentInterceptor); }}

[email protected] / @jkubrynski 12 / 48

Page 13: What you won't read in books about RESTful services

Cache headerscache-control: public, max-age=0, no-cache

public / privateno-cacheno-storemax-ages-maxage

[email protected] / @jkubrynski 13 / 48

Page 14: What you won't read in books about RESTful services

Cache headerscache-control: public, max-age=0, no-cache

public / privateno-cacheno-storemax-ages-maxage

ETag

If-None-Match: "0d41d8cd98f00b204e9800998ecf8427e"Spring brings ShallowEtagHeaderFilter

[email protected] / @jkubrynski 14 / 48

Page 15: What you won't read in books about RESTful services

Compressionreduces response size dramatically

in Tomcat extend Connector with

compression="on"compressionMinSize="2048"noCompressionUserAgents="gozilla, traviata"compressableMimeType="text/html,text/xml"

[email protected] / @jkubrynski 15 / 48

Page 16: What you won't read in books about RESTful services

HATEOASself-descriptive

client understands hypermedia

{ "name": "Alice", "links": [ { "rel": "self", "href": "/customers/1213" }, { "rel": "parent", "href": "/customers/14" }, { "rel": "currentOrder", "href": "/orders/14312" } ]}

HTTP/1.1 201 CreatedLocation: http://api.mydomain.com/orders/1234

[email protected] / @jkubrynski 16 / 48

Page 17: What you won't read in books about RESTful services

HATEOAS in Springpublic class Customer extends ResourceSupport { ... }// or wrap entity into Resource object

[email protected] / @jkubrynski 17 / 48

Page 18: What you won't read in books about RESTful services

HATEOAS in Springpublic class Customer extends ResourceSupport { ... }// or wrap entity into Resource object

import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*;

public HttpEntity<Customer> get(@PathVariable("id") String customerId) { Customer customer = repository.findOne(customerId); String pId = customer.getBoss(); String oId = customer.currentOrderId();

customer.add(linkTo(methodOn(CustomerController.class).get(customerId)).withSelfRel()); customer.add(linkTo(methodOn(CustomerController.class).get(pId)).withRel("parent")); customer.add(linkTo(methodOn(OrderController.class).get(oId)).withRel("currentOrder"));

return new ResponseEntity<Customer>(customer, HttpStatus.OK);}

public ResponseEntity create(@RequestBody Customer customer) { String id = repository.save(customer); return ResponseEntity.created(linkTo(CustomerController.class).slash(id).toUri()) .build();}

[email protected] / @jkubrynski 18 / 48

Page 19: What you won't read in books about RESTful services

@DanaDanger HTTP codes classification20x: cool

30x: ask that dude over there

40x: you fucked up

50x: we fucked up

[email protected] / @jkubrynski 19 / 48

Page 20: What you won't read in books about RESTful services

Exceptionsinclude detailed information

{ "status": 400, "code": 40483, "message": "Incorrect body signature", "moreInfo": "http://www.mycompany.com/errors/40483"}

[email protected] / @jkubrynski 20 / 48

Page 21: What you won't read in books about RESTful services

Exceptionsinclude detailed information

{ "status": 400, "code": 40483, "message": "Incorrect body signature", "moreInfo": "http://www.mycompany.com/errors/40483"}

hide stacktrace

[email protected] / @jkubrynski 21 / 48

Page 22: What you won't read in books about RESTful services

Handling Spring MVC exceptions@ControllerAdvicepublic class MyExceptionHandler extends ResponseEntityExceptionHandler {

/* Handling framework exceptions */ @Override protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers, HttpStatus status, WebRequest request) { LOG.error("Spring MVC exception occurred", ex); return super.handleExceptionInternal(ex, body, headers, status, request); }

/* Handling application exceptions */ @ResponseStatus(value = HttpStatus.NOT_FOUND) @ExceptionHandler(ResourceNotFoundException.class) public void handleResourceNotFound() { }}

[email protected] / @jkubrynski 22 / 48

Page 23: What you won't read in books about RESTful services

API Versioningdon't even think aboutapi.domain.com/v2/orders

URIs to the same resources should be fixed betweenversions

[email protected] / @jkubrynski 23 / 48

Page 24: What you won't read in books about RESTful services

API Versioningdon't even think aboutapi.domain.com/v2/orders

URIs to the same resources should be fixed betweenversions

use Content-Type

1 version: application/vnd.domain+json

2 version: application/vnd.domain.v2+json

[email protected] / @jkubrynski 24 / 48

Page 25: What you won't read in books about RESTful services

Filtering and sortingGET /reviews?rating=5

GET /reviews?rating=5&sortAsc=author

[email protected] / @jkubrynski 25 / 48

Page 26: What you won't read in books about RESTful services

Filtering and sortingGET /reviews?rating=5

GET /reviews?rating=5&sortAsc=author

Dynamic queries are easier in POST body

[email protected] / @jkubrynski 26 / 48

Page 27: What you won't read in books about RESTful services

Filtering and sortingGET /reviews?rating=5

GET /reviews?rating=5&sortAsc=author

Dynamic queries are easier in POST body

POST /reviews/searches

GET /reviews/searches/23?page=2

[email protected] / @jkubrynski 27 / 48

Page 28: What you won't read in books about RESTful services

Documentationrunnable with examples

Swagger

[email protected] / @jkubrynski 28 / 48

Page 29: What you won't read in books about RESTful services

[email protected] / @jkubrynski 29 / 48

Page 30: What you won't read in books about RESTful services

Stateless or not?password hashing cost

session replication

load-balancing

[email protected] / @jkubrynski 30 / 48

Page 31: What you won't read in books about RESTful services

Stateless or not?password hashing cost

session replication

load-balancing

...

stateless session?

[email protected] / @jkubrynski 31 / 48

Page 32: What you won't read in books about RESTful services

Avoiding session creation in Spring@EnableWebSecuritypublic class SpringSecurity extends WebSecurityConfigurerAdapter {

@Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() .authorizeRequests() .antMatchers("/secure/**").fullyAuthenticated() .and()

.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER)

.and() .httpBasic(); }}

[email protected] / @jkubrynski 32 / 48

Page 33: What you won't read in books about RESTful services

SecuritySQL Injection

XSS

CSRF

XXE

[email protected] / @jkubrynski 33 / 48

Page 34: What you won't read in books about RESTful services

HQL InjectionList<Product> products = em.createQuery( "SELECT p FROM Product p where p.category = '" + categ + "'", Product.class) .getResultList();

[email protected] / @jkubrynski 34 / 48

Page 35: What you won't read in books about RESTful services

HQL InjectionList<Product> products = em.createQuery( "SELECT p FROM Product p where p.category = '" + categ + "'", Product.class) .getResultList();

categ = ' OR '1'='1

[email protected] / @jkubrynski 35 / 48

Page 36: What you won't read in books about RESTful services

HQL InjectionList<Product> products = em.createQuery( "SELECT p FROM Product p where p.category = '" + categ + "'", Product.class) .getResultList();

categ = ' OR '1'='1

SELECT __fields__ FROM products WHERE category = '' OR '1'='1'

[email protected] / @jkubrynski 36 / 48

Page 37: What you won't read in books about RESTful services

HQL InjectionList<Product> products = em.createQuery( "SELECT p FROM Product p where p.category = '" + categ + "'", Product.class) .getResultList();

categ = ' OR '1'='1

SELECT __fields__ FROM products WHERE category = '' OR '1'='1'

List<Product> products = em.createQuery( "SELECT p FROM Product p where p.category = :categ", Product.class) .setParameter("categ", categ) .getResultList();

[email protected] / @jkubrynski 37 / 48

Page 38: What you won't read in books about RESTful services

HQL InjectionList<Product> products = em.createQuery( "SELECT p FROM Product p where p.category = '" + categ + "'", Product.class) .getResultList();

categ = ' OR '1'='1

SELECT __fields__ FROM products WHERE category = '' OR '1'='1'

List<Product> products = em.createQuery( "SELECT p FROM Product p where p.category = :categ", Product.class) .setParameter("categ", categ) .getResultList();

SELECT __fields__ FROM products WHERE category = ' OR ''1''=''1'''

[email protected] / @jkubrynski 38 / 48

Page 39: What you won't read in books about RESTful services

CSRF - Cross-site request forgery<img src="https://api.mybank.com/transfers/from/1233/to/1234/amount/5000">

<form action="https://api.mybank.com/transfers" method="POST"> <input type="hidden" name="from" value="1233"/> <input type="hidden" name="to" value="1234"/> <input type="hidden" name=amount" value="5000"/> <input type="submit" value="Celebrity Nude Photos!"/></form>

[email protected] / @jkubrynski 39 / 48

Page 40: What you won't read in books about RESTful services

CSRF - Cross-site request forgery<img src="https://api.mybank.com/transfers/from/1233/to/1234/amount/5000">

<form action="https://api.mybank.com/transfers" method="POST"> <input type="hidden" name="from" value="1233"/> <input type="hidden" name="to" value="1234"/> <input type="hidden" name=amount" value="5000"/> <input type="submit" value="Celebrity Nude Photos!"/></form>

One time request tokens

Correct CORS headers

[email protected] / @jkubrynski 40 / 48

Page 41: What you won't read in books about RESTful services

CORS - Cross Origin Requests SharingPreflight request

OPTIONS /cors HTTP/1.1Origin: http://www.domain.comAccess-Control-Request-Method: PUTAccess-Control-Request-Headers: X-Custom-HeaderHost: api.mydomain.orgAccept-Language: en-USConnection: keep-aliveUser-Agent: Mozilla/5.0...

Preflight response

Access-Control-Allow-Origin: http://www.domain.comAccess-Control-Allow-Methods: GET, POST, PUTAccess-Control-Allow-Headers: X-Custom-HeaderContent-Type: text/html; charset=utf-8

[email protected] / @jkubrynski 41 / 48

Page 42: What you won't read in books about RESTful services

XML External Entity<?xml version="1.0" encoding="utf-8"?><comment> <text>Yeah! I like it!</text></comment>

[email protected] / @jkubrynski 42 / 48

Page 43: What you won't read in books about RESTful services

XML External Entity<?xml version="1.0" encoding="utf-8"?><comment> <text>Yeah! I like it!</text></comment>

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE myentity [ <!ENTITY a "Yeah! I like it!"> ]><comment> <text>&a;</text></comment>

[email protected] / @jkubrynski 43 / 48

Page 44: What you won't read in books about RESTful services

XML External Entity<?xml version="1.0" encoding="utf-8"?><!DOCTYPE myentity [ <!ENTITY a SYSTEM "/etc/passwd"> ]><comment> <text>&a;</text></comment>

[email protected] / @jkubrynski 44 / 48

Page 45: What you won't read in books about RESTful services

XML External Entity<?xml version="1.0" encoding="utf-8"?><!DOCTYPE myentity [ <!ENTITY a SYSTEM "/etc/passwd"> ]><comment> <text>&a;</text></comment>

<?xml version="1.0" encoding="utf-8"?><comment> <text>root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt ..... </text></comment>

[email protected] / @jkubrynski 45 / 48

Page 46: What you won't read in books about RESTful services

XML External Entity<?xml version="1.0" encoding="utf-8"?><!DOCTYPE myentity [<!ENTITY a "abcdefghij1234567890" > <!ENTITY b "&a;&a;&a;&a;&a;&a;&a;&a;&a;&a" > <!ENTITY c "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;" > <!ENTITY d "&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;" > ...<!ENTITY h "&g;&g;&g;&g;&g;&g;&g;&g;&g;&g;" >]><comment> <text>&h;</text></comment>

[email protected] / @jkubrynski 46 / 48

Page 47: What you won't read in books about RESTful services

http://knowyourmeme.com/photos/531557 thx to @mihn

[email protected] / @jkubrynski 47 / 48

Page 48: What you won't read in books about RESTful services

Thanks!

[email protected] / @jkubrynski 48 / 48