iT邦幫忙

2021 iThome 鐵人賽

DAY 6
0
自我挑戰組

Angular+Spring Boot API 處理股市資料系列 第 6

JWT實作(二)(Day6)

要利用帳號密碼驗證使用者,首先我們必須要有使用者(廢話?
在 stockapi資料庫裡面新增一個表單(user)

CREATE TABLE users (
ID INT NOT NULL AUTO_INCREMENT COMMENT '使用者ID',
ACCOUNT VARCHAR(50) NOT NULL DEFAULT '0' COMMENT '使用者帳號',
NAME VARCHAR(50) NOT NULL DEFAULT '0' COMMENT '使用者姓名',
PASSWORD VARCHAR(60) NOT NULL DEFAULT '0' COMMENT '使用者密碼(加密過)',
PRIMARY KEY (ID)
)
COMMENT='使用者'
COLLATE='utf8_general_ci';

在pom.xml再引入兩個套件,使我們可以與資料庫進行溝通

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>

接著我們必須要創建使用者

1.創建與資料庫溝通的類別
新建一個 package - repository
新增一個 Class - UserRepository

package com.stockAPI.repository;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;

import com.stockAPI.model.User;

@Repository
public class UserRepository {

	@Autowired
	NamedParameterJdbcTemplate namedParameterJdbcTemplate;
	
	public Integer add(User user) {
		KeyHolder keyHolder = new GeneratedKeyHolder();
		SqlParameterSource sqlParameterSource=new BeanPropertySqlParameterSource(user);
		String sql = " INSERT INTO stockapi.users ( ACCOUNT, NAME, PASSWORD ) "
				   + " VALUE ( :account, :name, :password ) " ;
		namedParameterJdbcTemplate.update(sql, sqlParameterSource,keyHolder);
		return keyHolder.getKey().intValue();
	}

這邊我們用NameParameterJdbcTemplate與JdbcTemplate的差異在於,他可以 :參數名稱
而不是利用 ? 號這樣的代位符號,好處是可以避免因為參數塞入的順序錯誤,而導致SQL
語法報錯。
NameParameterJdbcTemplate實際上也是透過重新包裝JdbcTemplate產生的模板,因此他們的底層原理是一樣的。

2.實作StockUserServcie的業務邏輯
新建一個 package - service
新增一個Class - StockUserServcie 繼承 UserDetailServcie (之後登入會用到)

package com.stockAPI.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import com.stockAPI.model.User;
import com.stockAPI.repository.UserRepository;


@Service
public class StockUserService implements UserDetailsService {
	
	
	@Autowired
	UserRepository userRepository;
	
	//載入套件的加密器
	@Autowired
	BCryptPasswordEncoder bCryptPasswordEncoder;

	//目前還沒要用到,先不實作
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		return null;
		
	}
	
	public Integer addUser(User user) {
		user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
		Integer user_id = userRepository.add(user);
		return user_id;
	}
}

3.修改security設定並註冊加密器

@Override
    protected void configure(HttpSecurity http) throws Exception {
    	http
    		.authorizeRequests()
    		.antMatchers("/user/testBlock").authenticated()
    		.antMatchers("/user/testUnblock").permitAll()
    		.antMatchers("/user/create").permitAll()
    		.and()
    		.csrf().disable(); 
        
    }
    
    //加密器注入容器
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

csrf().disable(); 必須啟用,不然外部網域無法請求,這與我們接下來要用postman測試有關

4.新增API回傳物件

package com.stockAPI.model;

import java.util.Map;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class APIReturnObject {
	
	private String message;
	
	private Map<String, Object> data;

}

5.新增controller路徑設置

@PostMapping("create")
public APIReturnObject create(@RequestBody User user) {
APIReturnObject result = new APIReturnObject();
Map<String, Object> data = new HashMap<String, Object>();
Integer user_id = stockUserService.addUser(user);
data.put("user_id", user_id);
result.setMessage("用戶資料新增成功");
result.setData(data);
return result;
}

我們目前預設 如果用戶資料新增成功會回傳 用戶ID

再來是註冊postman
https://www.notion.so/JWT-daf2d86fbaa44554a10675f13db40b31#6730f3d3efdb4de8bded483ed4680288
記得安裝postman Desktop版本

接著
https://ithelp.ithome.com.tw/upload/images/20210921/20138857zcG2U5cllZ.png

設定好 網址、方法、參數 按 Send

就可以看到
https://ithelp.ithome.com.tw/upload/images/20210921/20138857UCe42vYI4S.png

請注意一件事,因為我們Controller接受參數的註解使用的是 @RequestBody 因此參數
不要塞錯塞到Params,這樣Controller會因為接受不到參數而報錯喔!!

這時候你一定會有疑問,會員新增的權限是誰都可以嗎? 我們要怎麼判斷權限?
這些留待我們明天繼續說明~~


上一篇
JWT實作(一)(Day5)
下一篇
JWT實作(三)(Day7)
系列文
Angular+Spring Boot API 處理股市資料32

尚未有邦友留言

立即登入留言