1. 程式人生 > 程式設計 >Spring Security 在前後端分離專案中的實踐(1)

Spring Security 在前後端分離專案中的實踐(1)

1 概述

如今,前後端分離(開發)已經非常常見了。由於任務需要,要在基於 Spring Boot 的 Web 專案中整合 Spring Security 完成使用者模組的登入和認證等功能,但是在網上查閱的(中文)資料中,對前後端完全分離如何配置 Spring Security 都描述的不是很清楚,而這篇文章也是自己對前後端分離配置 Spring Security 的探究。

2 實踐

2.1 版本

基於 SpringBoot 2.1.8.RELEASE,基於起步依賴 spring-boot-starter-security (Spring Security 5)

2.2 Spring Security 相關配置

使用者認證:

@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception{
        auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
    }
複製程式碼

對應的 userDetailsService 實現:

@Component("myUserDetailsService")
public class MyUserDetailsService implements UserDetailsService {

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 這裡設計為任何密碼為 123456 的使用者都可以通過驗證
        String password = new BCryptPasswordEncoder().encode("123456"
); User user = new User(username,password,AuthorityUtils.commaSeparatedStringToAuthorityList("admin")); return user; } } 複製程式碼

HttpSecurity 相關配置:

@Override
    protected void configure(HttpSecurity http) throws Exception{
        //未登入時訪問 Security 保護的介面
        http.httpBasic().authenticationEntryPoint(new AuthenticationEntryPoint
(){ @Override public void commence(HttpServletRequest request,HttpServletResponse response,AuthenticationException authException) throws IOException,ServletException { response.setContentType("application/json;charset=UTF-8"); response.getWriter().append(new ObjectMapper().writeValueAsString(Response.createByError("未登入"))); } }); http.authorizeRequests() .antMatchers("/user/login").permitAll() .anyRequest().authenticated() .and() .formLogin() .loginProcessingUrl("/user/login") .successForwardUrl("/user/login") // 登入成功後的“跳轉”介面 .failureForwardUrl("/user/loginfail") //登入失敗後的“跳轉”介面 .and().csrf().disable(); } 複製程式碼

這裡是有關對 Spring Security 在前後端分離的核心疑問:前後端分離設計下,在 Spring Security 認證成功後跳轉到登入介面是否是合理的設計,認證失敗時跳轉到指定介面是否合理

下面是相關控制器的實現:

// 能訪問到 login 介面都是登入成功,在邏輯功能上是合理的,但是不知道設計上是否合理,是否存在 BUG?
    @RequestMapping(value = "/login",method = RequestMethod.POST)
    public Response login(){
        return Response.createByError("登陸成功");
    }

    @RequestMapping(value = "/detail",method = RequestMethod.POST)
    public Response getDetail(){
        Map<String,String> map = new HashMap<>();
        map.put("username","chen");
        map.put("password","******");
        return Response.createBySuccessWithData(map);
    }
// 為登入失敗設計一個介面是否合理?
    @RequestMapping(value = "/loginfail",method = RequestMethod.POST)
    public Response loginFail(){
        return Response.createByError("使用者名稱或密碼錯誤");
    }
複製程式碼

2.3 測試

完成相關程式碼,啟動程式,使用 postman 進行介面訪問的簡單測試: 未登入訪問 /user/detail 介面

001.png
登入認證失敗
002.png
登入認證成功
003.png
登入認證成功後再次訪問 /user/detail 介面
004.png

3 問題總結

綜合全文,目前還存在的疑問和待解決的問題包括: 1)Spring Security 在前後端分離設計下如何設計相關介面?驗證成功後“跳轉”到指定介面是否合理,驗證失敗後“跳轉”到特定認證失敗介面的設計是否合理?不合理該如何設計?合理的話對應介面的設計應該注意些什麼? 2)Spring Security 是如何獲取提交的表單欄位的?本示例程式碼對於表單中的請求欄位不為或不存在 username 和 password 丟擲的異常沒有進行處理,會“跳轉”到上述特定認證失敗介面。

如果有對 Spring Security 瞭解的小夥伴,希望不吝賜教,留言解答我的疑惑,不勝感激!

4 Demo 地址

gitee.com/itschenxian…