我們現在設定兩種權限,管理員(ADMIN)&正常(NORMAL)
要實作權限功能,我們先在users表單新增 AUTHORITY欄位,預設如果沒有輸入的話是 NORMAL權限
ALTER TABLE `stockapi`.`users`
ADD COLUMN `AUTHORITY` VARCHAR(45) NOT NULL DEFAULT 'NORMAL' COMMENT '權限' AFTER `PASSWORD`;
修改User 類別的屬性, 新增authority,再加上無參數的建構子不然BeanRowMapper無法初始化
package com.stockAPI.model;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class User {
private Integer id;
private String account;
private String name;
private String password;
private String authority;
//需加入無參數的建構子,不然BeanRowMapper無法初始化
public User(){
}
public User(String account,String name,String password,String authority) {
this.account=account;
this.name=name;
this.password=password;
}
}
修改StockUser的getAuthorities() 方法,之前是預設回傳空陣列
package com.stockAPI.model;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class StockUser implements UserDetails {
private static final long serialVersionUID = 1L;
private User user;
public StockUser(User user) {
this.user=user;
}
//取得此帳號的權限
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<SimpleGrantedAuthority> authority_list = new ArrayList<SimpleGrantedAuthority>();
authority_list.add(new SimpleGrantedAuthority(user.getAuthority()));
return authority_list;
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getAccount();
}
//驗證此帳號是否未過期,目前沒有要用到先設return true
@Override
public boolean isAccountNonExpired() {
return true;
}
//驗證此帳號是否未被封鎖,目前沒有要用到先設return true
@Override
public boolean isAccountNonLocked() {
return true;
}
//驗證此帳號憑證是否未過期,目前沒有要用到先設return true
@Override
public boolean isCredentialsNonExpired() {
return true;
}
//驗證此帳號是否可以使用,目前沒有要用到先設return true
@Override
public boolean isEnabled() {
return true;
}
}
接著為了與新增會員的權限作區別(只有管理員可以新增會員)
我們實作一個新功能是根據帳號查詢自己資料(大家都可以使用)
在StockUserService新增一個方法是 getOwnData
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.StockUser;
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 {
User user= userRepository.getDataByAccount(username);
return new StockUser(user);
}
public Integer addUser(User user) {
user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
Integer user_id = userRepository.add(user);
return user_id;
}
public StockUser getOwnData(String account){
User user= userRepository.getDataByAccount(account);
//資料內不可以含有密碼資訊
user.setPassword(null);
return new StockUser(user);
}
}
在UserController 新增查詢連結
package com.stockAPI.controller;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.stockAPI.model.APIReturnObject;
import com.stockAPI.model.StockUser;
import com.stockAPI.model.User;
import com.stockAPI.service.StockUserService;
@RestController
@RequestMapping("user")
public class UserController {
@Autowired
StockUserService stockUserService;
@GetMapping("testBlock")
public String testBlock() {
return "testBlock";
}
@GetMapping("testUnblock")
public String testUnblock() {
return "testUnblock";
}
@GetMapping("search/{account}")
public APIReturnObject search(@PathVariable(name="account") String account) {
APIReturnObject result = new APIReturnObject();
Map<String, Object> data = new HashMap<String, Object>();
StockUser stockUser = stockUserService.getOwnData(account);
data.put("userData", stockUser.getUser());
result.setMessage("用戶資料查詢成功");
result.setData(data);
return result;
}
@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;
}
}
再來是我們修改Security的設定,並設定查詢連結是所有人都可以使用的
package com.stockAPI.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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 com.stockAPI.service.StockUserService;
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
StockUserService stockUserService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/user/testUnblock").permitAll()
.antMatchers("/user/create").hasAuthority("ADMIN") //管理員可以新增使用者資料
.antMatchers("/user/search/**").permitAll() //大家都可以查詢資料
.and()
.csrf().disable();
}
//先把加密器注入容器
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}
這時候讓我們用postman 測試一下
url:http://localhost:8080/user/search/ken123
method:GET
就可以看到資料出現囉
然後再試著執行我們之前創建使用者的請求,就會發現因為設定權限所以我們已經不能請求成功了喔
咦! 那我們要怎麼讓系統去辨認我們的權限呢?
這就與我們明天要實作的登入功能有關囉~!!