REST (Representational State Transfer)とは
- URLを叩くと各種Webサービスを実行することができます
- 例えば、yahoo天気情報などを取得する
- AIや天気情報、地図検索、経路検索などを実行する、など
- 通常のHTMLリクエストを送ると、HTMLがレスポンスとして返ってきて、ブラウザでは、返ってきたHTMLを画面に表示する
- RESTではHTMLリクエストを送ると、Webサービスの実行結果が返る
- →アプリケーションから外部サービスを利用することができる!
- 既にあるサービスを使えば、開発効率UPすることができます💮
- RESTではJSON形式でレスポンスを返すのがメイン
RESTサービス実装の準備
- ユーザ情報を取得、登録、更新、削除するRESTサービスを実装します
RestService.java
package com.example.demo.login.domain.service;
import java.util.List;
import com.example.demo.login.domain.model.User;
public interface RestService {
//1件登録用メソッド
public boolean insert(User user);
//1件検索用メソッド
public User selectOne(String userId);
//全件検索用メソッド
public List<User> selectMany();
//1件更新用メソッド
public boolean update(User user);
//1件削除用メソッド
public boolean delete(String userId);
}
インターフェース実装クラスを作成
RestServiceJdbcImpl.java
package com.example.demo.login.domain.service.jdbc;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.example.demo.login.domain.model.User;
import com.example.demo.login.domain.repository.UserDao;
import com.example.demo.login.domain.service.RestService;
@Transactional
@Service
public class RestServiceJdbcImpl implements RestService {
@Autowired
@Qualifier("UserDaoJdbcImpl")
UserDao dao;
//1件登録用メソッド
@Override
public boolean insert(User user) {
int result = dao.insertOne(user);
return false;
}
//1件検索用メソッド
@Override
public User selectOne(String userId) {
return null;
}
//全件検索用メソッド
@Override
public List<User> selectMany() {
return null;
}
//1件更新用メソッド
@Override
public boolean update(User user) {
return false;
}
//1件削除用メソッド
@Override
public boolean delete(String userId) {
return false;
}
}
コントローラクラス
@RestController
- REST用のコントローラークラスには、@RestControllerアノテーションを付けます
UserRestController.java
package com.example.demo.login.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.login.domain.service.RestService;
@RestController
public class UserRestController {
@Autowired
RestService service;
}
セキュリティの設定
- RESTサービスを作る前に、セキュリティの設定をします
- RESTサービスのみCSRF対策を無効にし、Springが用意しているRequestMatcherを実装したクラスを作成します。
- このクラスの中では、GETメソッドおよび、指定されたURLの場合、CSRF対策のチェックをしないようにします。
- RestMatcherの設定をSecurityConfig.javaに反映します
RestMatcher.java
package com.example.demo;
import javax.servlet.http.HttpServletRequest;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
public class RestMatcher implements RequestMatcher {
//マッチャー
private AntPathRequestMatcher matcher;
//コンストラクタ
public RestMatcher(String url) {
super();
matcher = new AntPathRequestMatcher(url);
}
//URLのマッチ条件
@Override
public boolean matches(HttpServletRequest request) {
// GETならCSRFのチェックはしない
if ("GET".equals(request.getMethod())){
return false;
}
// 特定のURLに該当する場合、CSRFチェックしない
if (matcher.matches(request)){
return false;
}
return true;
}
}
SecurityConfig.java
package com.example.demo;
import javax.sql.DataSource;
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.builders.WebSecurity;
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;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// データソース
@Autowired
private DataSource dataSource;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
// ユーザーIDとパスワードを取得するSQL文
private static final String USER_SQL = "SELECT"
+ " user_id,"
+ " password,"
+ " true"
+ " FROM"
+ " m_user"
+ " WHERE"
+ " user_id = ?";
// ユーザーのロールを取得するSQL文
private static final String ROLE_SQL = "SELECT"
+ " user_id,"
+ " role"
+ " FROM"
+ " m_user"
+ " WHERE"
+ " user_id = ?";
@Override
public void configure(WebSecurity web) throws Exception {
//静的リソースへのアクセスには、セキュリティを適用しない
web.ignoring().antMatchers("/webjars/∗∗", "/css/∗∗");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// ログイン不要ページの設定
http
.authorizeRequests()
.antMatchers("/webjars/**").permitAll() //webjarsへアクセス許可
.antMatchers("/css/**").permitAll() //cssへアクセス許可
.antMatchers("/login").permitAll() //ログインページは直リンクOK
.antMatchers("/signup").permitAll() //ユーザー登録画面は直リンクOK
.antMatchers("/rest/**").permitAll() //RESTは直リンクOK
.antMatchers("/admin").hasAuthority("ROLE_ADMIN") //アドミンユーザーに許可
.anyRequest().authenticated(); //それ以外は直リンク禁止
//ログイン処理
http
.formLogin()
.loginProcessingUrl("/login") //ログイン処理のパス
.loginPage("/login") //ログインページの指定
.failureUrl("/login") //ログイン失敗時の遷移先
.usernameParameter("userId") //ログインページのユーザーID
.passwordParameter("password") //ログインページのパスワード
.defaultSuccessUrl("/home", true); //ログイン成功後の遷移先
//ログアウト処理
http
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout")) //
.logoutUrl("/logout") //ログアウトのURL
.logoutSuccessUrl("/login"); //ログアウト成功後のURL
//CSRFを無効にするURLを設定
RequestMatcher csrfMatcher = new RestMatcher("/rest/**");
//RESTのみCSRF対策を無効に設定
http.csrf().requireCsrfProtectionMatcher(csrfMatcher);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// ログイン処理時のユーザー情報を、DBから取得する
auth.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery(USER_SQL)
.authoritiesByUsernameQuery(ROLE_SQL)
.passwordEncoder(passwordEncoder());
}
}
GETメソッドの実装
- 先ほどのインターフェース実装クラス、Controllerクラスを編集します
- RESTコントローラクラスでメソッドに@GetMappingアノテーションをつけるだけ
- @RestControllerアノテーションを付けたクラスの各メソッドの戻り値に、htmlファイル以外を指定できます
RestServiceJdbcImpl.java
//中略
//1件検索用メソッド
@Override
public User selectOne(String userId) {
return dao.selectOne(userId);
}
//全件検索用メソッド
@Override
public List<User> selectMany() {
return dao.selectMany();
}
//中略
UserRestController.java
package com.example.demo.login.controller;
import java.util.List;
import com.example.demo.login.domain.model.User;
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.RestController;
import com.example.demo.login.domain.service.RestService;
@RestController
public class UserRestController {
@Autowired
RestService service;
/**
* ユーザー全件取得
*/
@GetMapping("/rest/get")
public List<User> getUserMany() {
// ユーザー全件取得
return service.selectMany();
}
/**
* ユーザー1件取得
*/
@GetMapping("/rest/get/{id:.+}")
public User getUserOne(@PathVariable("id") String userId) {
// ユーザー1件取得
return service.selectOne(userId);
}
}
起動してGETメソッド実行!
- ユーザ一覧を取得
- http://localhost:8080/rest/get
- ユーザIDを指定して取得
- http://localhost:8080/rest/get/yamada@xxx.co.jp
- →yamadaのデータのみ帰ってきました〜^^