SpringSecurity 開發安全的RESTful服務(持續更新)

SpringSecurity 開發安全的RESTful服務

一. 初入RESTful

1.1 本章導航

  • 使用Spring MVC編寫Restful API
  • 使用Spring MVC處理其他web應用常見的需求和場景
  • Restful API開發常用輔助框架

1.2 使用SpringMVC 編寫RESTful API

  • 使用Restful API的第一印象如圖:
    在這裏插入圖片描述
  • 特點如下:
    1. 用URL描述資源
    2. 使用HTTP方法描述行爲。使用HTTP狀態碼來表示不同的結果
    3. 使用json交互數據
    4. RESTful只是一種風格,並不是強制的標準。

1.3 REST成熟度模型

  • 如圖:
    在這裏插入圖片描述

1.4 常用註解

  • 映射註解:
    • @RestController:標明此Controller提供RestAPI
    • @RequestMapping及其變體:映射http請求url到java方法
    • @RequestParam 映射請求參數到java方法的參數
  • 請求映射簡寫舉例:
    • Get請求舉例:
      @RequestMapping(value="/demo",method=RequestMethod.GET)
      
    • Get請求簡寫後舉例:
      @GetMapping("demo")
      

      這裏的Get請求可以省略method,直接將@RequestMapping改爲@GetMapping,同時當括號內只有一個值的時候,value可以忽略,而"/"可以忽略,Spring會自己加上。其他的如增刪改都如此。

  • 分頁註解:
    1. 分頁對象: Pageeable: 它是Spring提供的一個分頁對象,當前端需要進行分頁查詢的時候,我們可以使用此對象進行分頁;
    2. 分頁註解:@PageableDefault: 可以對分頁對象進行分頁 ,示例如下:
    public void mthod(Model1 model1, @PageableDefault(page=2,size=17,sort="username,asc")Pageable pageable);
    
  • 傳參註解:
    • @PathVariable: 映射url片段到java方法的參數,在url聲明中使用正則表達式
      • 使用@PathVariable可以指定名稱(name=“變量名”),這樣就可以將變量映射到這個參數上,如果不進行映射,則必須要保證參數名和上面的@RequestMapping()內的{變量名}與其一致。
      • 映射的使用@PathVariable的前提條件是 映射的接口有一個{變量名} 進行映射,同時在方法內加上@PathVariable註解即可;示例如下:
      @RequestMapping("user/{id}")
      public User getInfo(@PathVariable String id){
      	...
      }
      
      • 可以添加正則表達式,如圖:
        在這裏插入圖片描述
    • @JsonView控制json輸出內容
      • 使用接口來聲明多個視圖
      • 在值對象的get方法上指定視圖
      • 在Controller方法上指定視圖
        • User 實體類 -> 定義接口 和 指定視圖
        public class User{
        	public interface UserSimpleView {};
        	public interface UserDetailView extends UserSimpleView {};
        	private String username;
        	private String p@ssw0rd;
        	@JsonView(UserSimpleView.class)
        	public String getUsername(){return username};
        	public void setUsername(String username){this.username = username;}
        	@JsonView(UserDetailView.class)
        	public String getPassword(){return password}
        }
        
      • 在Controller層上指定視圖:
        @RequestMapping(value="/user",method= RequestMethod.GET)
        @JsonView(User.UserSimpleView.class)
        public List<User> query(UserQueryCondition condition,@PageableDefault(page=2,size = 17 ,sort ="user,desc") Pageable pageable){
        	System.out.println(pageable.getPageSize());
        	System.out.println(pageable.getPageNumber());
        	System.out.println(pageable.getSort());
        	List<User> users=new ArrayList<>();
        	users.add(new User());
        	return users;
        }
        
        @RequestMapping(value="/user/{id://d+}",method=RequestMethod.GET)
        @JsonView(User.UserDetailView.class)
        public User getInfo(@PathVariable String id)
        public User getInfo(@PathVariable String id){
        	User user=new User();
        	user.setUsername("user");
        	return user;
        }
        

        @JsonView的作用就是在相同的對象,我們可以手動控制返回哪些字段。一個對象中的字段可以進行篩選,只返回其中的部分字段。

  • @RequestBody 映射請求體到java方法的參數

    當前端傳到後端是一個JSON格式的字符串的時候,後端是無法直接解析的,需要在參數前加上這個註解;

  • @Valid註解和BindingResult驗證請求參數的合法性並處理校驗結果。
    • 使用@Valid 的話,可以開啓校驗。如果在實體類中配置瞭如 @NotBlank等註解,就會在執行方法前先校驗參數,如果不符合要求則直接返回失敗。但是如果傳入了參數: BindingResult 對象的時候,可以將報錯信息存入此對象中,我們可以進一步處理,不必直接返回。如圖所示:
      在這裏插入圖片描述

    在pom.xml中加入spring-boot-maven-plugin的插件,可以打包出可以直接執行的jar包(會包含引入的依賴的jar包。)

  • 其他常用註解:
    • 常用的驗證註解
      • 如圖:
        在這裏插入圖片描述
        在這裏插入圖片描述

        這些所有的註解都有一個共有的值,叫做message,它可以自定義錯誤信息;如:

        	@NotBlank(message="密碼不能爲空")
        	private String password;
        
    • 自定義消息
      • 自定義校驗器:
        public class MyConstraintValidator implements ConstraintValidator<MyContraint,Object>{
        
        @Autowired
        private HelloService helloService;
        
        @Override
        private void initialize(MyConstraint constraintAnnotation){
        	System.out.println("my validator init");
        }
        @Override
        public boolean isValid(Object value,ConstraintValidatorContext context){
        	helloService.greeting("tom");
        	System.out.println(value);
        	return true;
        }
        }
        
      • 編寫註解類:
        @Target({ElementType.METHOD,ElementType.FIELD})
        @Retention(RetentionPolicy.RUNTIME)
        @Constraint(validatedBy= MyConstraintValidator.class)
        public @interface MyConstraint{
        	String message();
        	Class<?>[] groups() default{};
        	Class<? extends Plyload>[] payload() default{};
        }
        

        裏面的message,groups和plyload這三個是必不可少的,每個註解類都需要這個。

      • 使用自定義註解:
        在這裏插入圖片描述
    • 自定義校驗註解

1.5 RESTful錯誤機制

  • 本節內容:
    • Spring Boot中默認的錯誤處理機制

      • SpringBoot 的一個默認機制就是會去判斷,請求是瀏覽器發送的還是手機發送的。如果是錯誤信息的話,SpringBoot能夠根據不同的設備,返回不一樣的數據格式;比如:手機返回json,瀏覽器返回html頁面等
      • 在指定目錄下(error)下寫對應的頁面,當瀏覽器訪問時出現了對應的錯誤時,就會自動跳轉到對應的頁面中。如圖所示:
    • 自定義異常處理

      1. 首先創建一個自定義異常類:(可以創建一個包Package叫做exception,將此類放到下面)
        public class UserNotExistException extends RuntimeException{
        	private static final long serialVersionUID= -6112780192479692859L;
        	private String id;
        	public UserNotExistException(String id){
        		super("user not exit");
        		this.is = is;
        	}
        	//   id  的get,set方法省略...
        }
        
      2. 在接口中使用自定義的異常類:
        @GetMapping("/{id:\\d+}")
        @JsonView(User.UserDetailView.class)
        public User getInfo(@PathVariable String id){
        	throw new UserNotExistException(“user not exist”);
        }
        
      3. 設置統一異常處理:
        @ControllerAdvice
        public class ControllerExceptionHandler{
        	@ExceptionHandler(UserNotExistException.class)
        	@ResponseBody
        	@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
        	public Map<String,Object> handleUserNotExistException(UserNotExisException ex){
        		Map<String,Object> result=new HashMap<>();
        		result.put("id",ex.getId());
        		result.put("message",ex.getMessage());
        		return result;
        	}
        }
        
        • @ControllerAdvice,是Spring3.2提供的新註解,它是一個Controller增強器,可對controller中被 @RequestMapping註解的方法加一些邏輯處理。最常用的就是異常處理
        • 在@ExceptionHandler中指定了異常類。這樣在拋出了此異常後就可以做統一異常處理了。

1.6 RESTful攔截機制

  • 本節介紹內容

    • 過濾器(Filter)
    • 攔截器
    • 切片
  • 過濾器:

    • 手寫一個過濾器:
      @Component
      public class TimeFIlter implements Filter{
      @Override
      public void destroy(){
      	System.out.println("time filter destroy ");
      }
      @Override
      public void doFilter(ServletRequest request,ServletResponse response, FilterChain chain) throws IOException,ServletException{
      	System.out.println("time filter start");
      	long start =new Date().getTime();
      	chain.doFilter(request,response);
      	System.out.println("time filter:"+ (new Date().getTime()-start));
      	System.out.println("time filter finish");
      }
      	@Override
      	public void init(FilterConfig arg0) throws ServletException{
      		System.out.println("time filter init");
      	}
      }	
      

      如destroy 是結束時進入的方法,init是服務啓動時會執行的方法,doFilter是方法被執行前被調用和執行後的方法。使用過濾器可以攔截服務請求。

    • 如何把第三方沒有@Component註解的過濾器加入到過濾器鏈上去,也可以將我們自己寫的過濾器去掉@Component,然後通過下方去註冊加上去。方法如下:
      • 創建一個配置類:WebConfig
        @Configuration
        public class WebConfig{
        	@Bean
        	public FilterRegistrationBean timeFilter(){
        		FilterRegistrationBean registrationBean =new FilterRegistrationBean();
        		TimeFilter timeFilter=new TimeFilter();
        		registrationBean.setFilter(timeFilter);
        		List<String> urls=new ArrayList<>();
        		url.add("/*");
        		registrationBean.setUrlPatterns(urls);
        		return registratonBean;
        	}
        }
        
發佈了124 篇原創文章 · 獲贊 51 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章