javascript
如何使用Spring设置安全的REST API
眾所周知, Spring Boot是一個工具包,可以快速輕松地開發功能強大的Web服務。 它非常模塊化,可以與其他框架和工具很好地配合使用。 在本教程中,我將向您展示通過使用Speedment作為ORM對現有SQL數據庫設置RESTful API多么容易。
背景
Speedment是一個開放源代碼工具包 ,它連接到數據庫,分析元數據,并使用它生成實體和管理器類,以面向對象的方式對數據庫進行建模。 它還包含一個運行時庫,該庫將Java 8 Streams轉換為優化的SQL查詢,使您可以使用非常類型安全和現代的方式編寫代碼。 事實證明,這對于Spring應用程序來說是完美的。
本教程的目標
本教程的目標是使用Spring開發REST API,該API會根據用戶的角色授予對不同端點的訪問權限。 如果您想向前看,可以在這里的指南中找到所有資源 。
| POST /帳戶 | 任何人都可以訪問 |
| GET /帳戶/ {id} | 可供管理員以及相關用戶訪問 |
| GET /帳戶 | 列出所有帳戶,并且只有管理員可以訪問 |
將使用我們將使用標準Java 8 Streams查詢的MySQL數據庫進行身份驗證。 最后,我們將準備好一個完全面向對象的解決方案,可以使用自定義業務邏輯進行擴展!
如果您想跟隨完成的項目,可以在GitHub上克隆它。
步驟1:數據庫
為了簡單起見,我使用的是使用以下語句創建的自定義MySQL數據庫。 但是,您的想法是可以使用碰巧有權訪問的任何現有數據庫。
create database `securerest`; use `securerest`;create table `account` (`id` bigint not null auto_increment primary key,`username` varchar(30) not null unique,`password` char(60) not null,`role` enum('USER', 'ADMIN') not null );步驟2:創建Maven項目
為了快速啟動一個新的Spring項目,我推薦一個很棒的Spring Initializr網站。 在這里,您可以輕松輸入項目所需的依賴項。
我們需要以下Spring依賴項:
- spring-boot-starter-security
- 彈簧啟動啟動器網站
- MySQL的連接器的Java
其次,我們還需要添加Speedment依賴項以及Speedment插件來生成我們的代碼。
<dependency><groupId>com.speedment</groupId><artifactId>runtime</artifactId><version>${speedment.version}</version><type>pom</type> </dependency> ... <plugin><groupId>com.speedment</groupId><artifactId>speedment-maven-plugin</artifactId><version>${speedment.version}</version><dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.version}</version><scope>runtime</scope></dependency></dependencies> </plugin>步驟3:生成域模型
添加插件后,我們可以運行以下Maven目標來啟動Speedment UI。
mvn speedment:tool
這將打開“加速工具”。 它將要求您提供數據庫的用戶名,密碼,架構名稱等。 輸入字段的值,然后按“連接”。
在用戶界面內,您可以執行許多配置。 您可以指定所生成代碼的確切位置,禁用與應用程序無關的表或列,并在希望字段或表在代碼中以其他形式出現時創建別名。
對于本教程,按“生成”就足夠了。 現在,您應該看到如何在您的項目中生成許多新的Java類和包!
步驟4:配置Spring Security
為了允許Spring作為Spring Bean啟動Speedment,我們需要指定實例的創建方式。 為此,我們創建一個名為SpeedmentConfiguration的類。
SpeedmentConfiguration.java
@Configuration public class SpeedmentConfiguration {private @Value("${dbms.host}") String host;private @Value("${dbms.port}") int port;private @Value("${dbms.schema}") String schema;private @Value("${dbms.username}") String username;private @Value("${dbms.password}") String password;@Beanpublic SpeedmentApplication getSpeedmentApplication() {return new SpeedmentApplicationBuilder().withIpAddress(host).withPort(port).withUsername(username).withPassword(password).withSchema(schema).build();}@Beanpublic AccountManager getAccountManager(SpeedmentApplication app) {return app.getOrThrow(AccountManager.class);} }默認情況下,頂部的@Value字段是從名為application.properties的文件加載的。 因此,我們應該在此處指定值:
application.properties
# Speedment Settings dbms.host=localhost dbms.port=3306 dbms.schema=securerest dbms.username=root dbms.password=password# Server Settings server.port=9777接下來,我們需要創建用于用戶身份驗證的配置類。 我們稱此類為AuthenticationConfiguration。
AuthenticationConfiguration.java
@Configuration public class AuthenticationConfiguration extends GlobalAuthenticationConfigurerAdapter {private @Autowired AccountManager accounts;@Beanpublic DaoAuthenticationProvider authProvider() {final DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();authProvider.setUserDetailsService(getUserDetailsService());authProvider.setPasswordEncoder(getPasswordEncoder());return authProvider;}@Beanpublic UserDetailsService getUserDetailsService() {return username -> accounts.stream().filter(Account.USERNAME.equal(username)).findAny().orElseThrow(() -> new UsernameNotFoundException("Could not find the user '" + username + "'"));}@Beanpublic PasswordEncoder getPasswordEncoder() {return new BCryptPasswordEncoder();}@Overridepublic void init(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(getUserDetailsService()).passwordEncoder(getPasswordEncoder());} }注意我們如何在生成的AccountManager上使用@Autowired,因為它在SpeedmentConfiguration類中被指定為Spring Bean。
在方法getUserDetailsS??ervice()中,我們將Stream API與自定義謂詞一起使用,從而允許將流轉換為優化的SQL查詢。 但是,要使此方法起作用,我們需要做一件事。 我們需要確保生成的Account接口擴展了UserDetails,以便可以與Spring API無縫使用。 這很容易做到,因為Speedment不會覆蓋不是以“ Generated”開頭的文件。
Account.java
public interface Account extends GeneratedAccount, UserDetails {}我們還需要在實現類中添加一些方法來支持該接口。
AccountImpl.java
@JsonIgnoreProperties("password") public final class AccountImpl extends GeneratedAccountImpl implements Account {private static final long serialVersionUID = -7552975849070084309L;@Override @JsonIgnorepublic Collection<? extends GrantedAuthority> getAuthorities() {return createAuthorityList(getRole());}@Override @JsonIgnorepublic boolean isAccountNonExpired() {return true;}@Override @JsonIgnorepublic boolean isAccountNonLocked() {return true;}@Override @JsonIgnorepublic boolean isCredentialsNonExpired() {return true;}@Override @JsonIgnorepublic boolean isEnabled() {return true;} }然后,我們創建第三個配置文件,以定義訪問各種REST端點所需的權限。
SecurityConfiguration.java
@Configuration @EnableWebSecurity public class SecurityConfiguration extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers(POST, "/account").permitAll().antMatchers(GET, "/account").hasAuthority("ROLE_ADMIN").anyRequest().fullyAuthenticated().and().httpBasic().and().csrf().disable();} }步驟5:創建控制器
最后一步是在我們的業務邏輯所在的位置創建Controller類。 該類帶有@RestController批注,以允許Spring自動拾取它。 它定義了三個映射,每個REST端點一個。
AccountController.java
@RestController public class AccountController {private @Autowired AccountManager accounts;private @Autowired PasswordEncoder passwordEncoder;...}第一個端點是注冊命令。 它將位于“ POST /帳戶”上。 我們使用兩個參數,用戶名和密碼,對密碼進行哈希處理,然后將其持久保存到數據庫中。 如果用戶名已經存在,則該操作將失敗,因為用戶名在數據庫中被定義為UNIQUE。
@PostMapping("/account")long onPostAccount(@RequestParam("username") String username,@RequestParam("password") String password) {final Account created = accounts.persist(new AccountImpl().setUsername(username).setPassword(passwordEncoder.encode(password)).setRole("USER"));return created.getId();}接下來是“ GET / account”端點。 這很簡單。 我們將使用生成的管理器類啟動流。 然后,通過Speedment將流優化為SQL查詢。
@GetMapping("/account")List<Account> onGetAllAccounts() {return accounts.stream().collect(toList());}最后一個端點要復雜一些。 我們將Spring配置為僅允許登錄的用戶訪問“ GET / account {id}”,但是我們要確保用戶只能訪問自己的信息,除非他們具有“ ADMIN”角色。
@GetMapping("/account/{id}")Account onGetAccount(@PathVariable("id") long accountId,Authentication auth) {final Account account = (Account) auth.getPrincipal();if (account.getId() == accountId) {return account;} else if ("ADMIN".equals(account.getRole())) {return accounts.stream().filter(Account.ID.equal(accountId)).findAny().orElseThrow(NotFoundException::new);} else {throw new ForbiddenException();}}做完了! 現在,我們有了一個REST API,它使用數據庫來存儲用戶并使用基本身份驗證來確保用戶只能調用他們有權訪問的命令!
嘗試一下
要嘗試我們剛剛創建的REST API,只需啟動一個終端并使用cURL命令即可!
要注冊帳戶:
curl -X POST "http://localhost:9777/account?username=my_user&password=my_pass"要查看我們自己的信息(在這種情況下,我們是ID為1的用戶):
curl -X GET -u my_user:my_pass "http://localhost:9777/account/1"列出所有用戶(需要ADMIN角色):
curl -X GET -u my_user:my_pass "http://localhost:9777/account"摘要
在本教程中,我們創建了一個新的Spring Boot項目,以使用簡單的注冊系統快速映射RESTful API,并使用Speedment為該API生成面向對象的數據庫訪問層。 我們還配置了Spring Security來要求用戶進行身份驗證以訪問特定的端點。
有關如何使用Speedment的更多指南和教程, 請查看GitHub頁面 ! 您還可以在其中找到一些示例項目,這些示例項目說明了如何使用Speedment中提供的更多出色的代碼生成功能!
可以在這里找到本教程的完整資源!
直到下一次!
翻譯自: https://www.javacodegeeks.com/2017/03/set-secure-rest-api-spring.html
總結
以上是生活随笔為你收集整理的如何使用Spring设置安全的REST API的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux移动硬盘挂载(linux移动硬
- 下一篇: servlet3.0新特性_查看Serv