# 02.5-WebServic and APIs-Lesson5: Security
###### tags: `Udacity`
[ToC]
# 01 Introduction
{%youtube xlceysbunI8%}
# 02 Security Overview
{%youtube s3QU5kbUtes%}
When allowing access to data via web services, security is very important. We want to limit who can view or even update data; only trusted individuals should have access.
# 03 Authentication vs Authorization
{%youtube yCVRQgBPwqQ%}
**Authentication**
Authentication is about validating the identity of a client attempting to call a web service. Typically, identity is validated with user credentials, such as a user name and password.
**Authorization**
Authorization is the next step after authentication. So once a client is authenticated (they have proven who they are), what do they have access to? For example, what data can they view, are they allowed to change that data, etc.
There are two ways to authenticate with a web service
* API Key
* User name and password
==ShannonNote==
> * Authentication vs Authorization
> * Authentication
* 負責驗證client的身分
* Authorization
* 會在Authentication之後執行
* 會處理說這會client可以access那些data,能夠允許他們change the data?
# 04 Basic Authentication
{%youtube AFqFZS-6NW8%}
Basic Authentication (also referred to as Basic Auth) is the simplest protocol available for performing web service authentication over HTTP protocol. Basic Auth requires a username and password. The client calling the web service takes these two credentials, converts them to a single [Base 64–encoded value](https://en.wikipedia.org/wiki/Base64) and passes it along in the Authentication HTTP header.
The server compares the credentials passed to those stored. If it matches, the server fulfills the request and provides access to the data. If the Authentication HTTP header is missing or the password doesn’t match the user name, the server denies access and returns a [401 status code](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes), which means the request is Unauthorized.
==ShannonNote==
> * Basic Authentication
* 是個簡易的protocol for authentication
* 需要username and password
* client會呼叫webService取得username and password把他們轉變成single base 64 encoded
* 然後pass it along in authentication HTTP header
* Server會檢查reuqest進來的http header裡面的credential,是否match,如果match就會履行request和提供access to the data
* 如果不match,像是http header不見或是password不符合,就會回傳401錯誤代表request is unauthorized
> * API Key Authentication
* 另一種技術去secure Web Service
* Access透過一個unique key, like passcode
# 05 Spring Security
{%youtube 5U6qpTtV7vo%}
[Spring Security](https://spring.io/projects/spring-security) is a part of the Spring Framework and provides authentication, authorization and other security features for Spring-based applications.

==ShannonNote==
> * Spring Security
* 他是spring framwork的一部分,且他提供authentication和authorization還有一些security的功能for spring-base application
* 
> * REST API
* 假設我們有一個簡單的REST API回傳一連串的locations
* 順序是: Controller > Service > Repository > Location Data(H2)
# 06 Case Study
{%youtube qvIKMTcramM%}
The Security case study retrieves a list of locations from a database in a secure fashion. The code can be cloned from [GitLab](https://gitlab.com/videolearning/udacity-java/tree/master/Lesson5-security).
**The API has the following components:**
* Controller - LocationController.java
* Service - LocationService.java and LocationServiceImpl.java
* CRUD Repository - LocationRepository.java
* Domain Entity/Model - Location.java
* Security Configuration - SpringSecurityConfig.java
* H2 Database accessible via http://localhost:8080/h2/
* Tomcat Server accessible via http://localhost:8080
**CSRF**
Read more about Cross Site Request Forgery [here](https://en.m.wikipedia.org/wiki/Cross-site_request_forgery).
==ShannonNote==
* @Override Configure method setting
* `.csrf().disable()` : Cross-Site Request Forgery
* `.authorizedRequests().anyRequest().authentircated()`:表示all requests to the API requires authentication.
* `.httpBasic()`: 允許user使用http basic authentication
* @Override configureGlobal setting
* 設定in memory user
* `inMemoryAuthentication()`: inmemory要使用authentication
* `inMemoryAuthentication().withUser("user").(encoder().encod("password")).roles`: 設定可以access的使用者跟密碼還有腳色
* @Bean PasswordEncoder的類 encoder method
* 目的在encode密碼,密碼會透過base64去編碼
# 07 Lab: Secure Your Dog API
**Lab: Secure Your Dog API**
Reuse your Dog REST API code from Lesson 2 and secure it using Basic Authentication.
* **Step 1**: Add the necessary dependencies for Spring Security in the Maven POM file.
* **Step 2**: Create the necessary security configuration class that extends WebSecurityConfigurerAdapter to secure your API with Basic Authentication.
* **Step 3**: Test that your API is now secured with basic authentication and still operates appropriately for an authenticated user.
# 08 Lab: Solution: Secure Your Dog API
**Solution: Secure Your Dog API**
Below, we'll walk through each step of the lab and look at one potential way to implement the lab. Even if you get stuck, you should always first try to work through the lab without the solution before coming here, so that you can best learn the related skills and be ready for the project at the end of the course.
**Step 1: Add the necessary dependencies for Spring Security.**
Given your code for the REST API from before, you just need to add the following two dependencies to the Maven POM file:
```xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
</dependency>
```
**Step 2: Create the necessary security configuration class.**
* the class should extend WebSecurityConfigurerAdapter to secure your API with Basic Authentication
First, add a `config` package to your Dog REST API code, and then add a `SpringSecurityConfig` class within it that extends `WebSecurityConfigurerAdapter` from Spring Security.
From there, the code follows similarly to how the Location API was secured in the earlier Case Study video, although welcome to update the username and password used below (and required to do so in any more in-depth implementation, of course). Note that the class uses both the `@Configuration` and `@EnableWebSecurity` annotations.
```java=
package com.udacity.DogRestApi.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.httpBasic();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception {
auth.inMemoryAuthentication()
.withUser("admin")
.password(encoder().encode("password"))
.roles("USER");
}
@Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
}
```
Note in the above that all of the `.` functions are actually chain together, but are on separate lines so that someone reading the code can more easily understand it.
**Step 3: Test that your API is now secured.**
* It should use basic authentication
* The API should still operate appropriately for an authenticated user
You can test this out in multiple ways. First, I tried to access [localhost:8080/dogs](localhost:8080/dogs) in the browser, and got a "Sign in" window. If I click cancel, I get a 401 error - Unauthorized. If I enter in my basic authentication information, I can access the page.
> Needing to sign in to our Dog API

> The 401 status - Unauthorized

I can also test this in Postman instead, where I change the "Authorization" tab to use "Basic Auth", make sure I am using a `GET request`, and then first attempt without a username and password. I will again get a status code of 401 meaning I am unauthorized. If I add the correct username and password, I can access the API.

**Full Solution**
If you'd like the full solution code all in one place, you can download it through the link below.
Supporting Materials
[SecureDogApi](https://video.udacity-data.com/topher/2019/August/5d4c7179_securedogapi/securedogapi.zip)
# 09 Recap
{%youtube D-lGnr7VQEg%}
# 補充01: Base64
參考:
* https://en.wikipedia.org/wiki/Base64
* https://www.itread01.com/content/1544979986.html
> 甚麼是Base64?
Base64是常見用來傳輸8bit位元組編碼的方式之一,用64個Ascii可列印的字原來標示二進位置資料的方法,他是可逆的編碼方式,簡單來說將二進位置資料 編碼變成Ascii字元。
> 何時會使用?
1. 通常會用在http protocal傳輸二進位制資料,因為http protocal是文字protocal只能傳輸可列印字元,在ASCII中某些字是控制字元有些是可列印字元,哪 非可列印字元就可以透過Base64來傳輸。
2. 將圖片等原始檔用base64編碼職些放在程式碼中,如果要使用該圖片就用 反Base64 把她轉換成image物件使用
# 補充02: 401未經授權
參考: https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#4xx_Client_errors
401 semantically means "unauthorised",[33] the user does not have valid authentication credentials for the target resource.專門用於身分驗證且失敗或尚未提供身分驗證的情況,response必須包含www-authenticate header裡面包含所有request。
# 補充03: CSRF 跨站請求偽造
參考:https://zh.wikipedia.org/wiki/%E8%B7%A8%E7%AB%99%E8%AF%B7%E6%B1%82%E4%BC%AA%E9%80%A0
Cross-Site Request Forgery也被稱為one-click attack或是session riding,是一種挾制user在當前已經登入的web application上執行非本人操作的攻擊手法。
> 攻擊細節
簡單來說是攻擊者通過一些技術手段欺騙用戶的瀏覽器去存取一個自己曾經認證過的網站並執行一些操作(像是發郵件訊息或是轉帳購買產品),因為瀏覽器曾經驗證過所以被存取的網站會認為是真正的用戶操作而去執行,簡單的身分驗證只能保證請求發自某個用戶的瀏覽器,但不能保證請求本身是用戶自願發出。