SpringBoot 2整合SpringSecurity遇到的一個大坑

前言

這幾天一直在學習和慢慢摸索SpringBoot和SpringSecurity整合的知識要點,今天搭好了鑑權這一塊後啓動項目,準備用postman測一下幾個接口,沒想到遇到一個天坑(也許是自己才疏學淺了😄😄)。

首先在配置裏過濾掉不需要認證的URL:

 .antMatchers("/login","/home","/getCode").permitAll() //過濾不需要認證的路徑
                .antMatchers("/auth/**").permitAll() //過濾不需要認證的路徑
                .anyRequest().authenticated() //對任何一個請求,都需要認證

放開了/auth/下的接口,controller裏的方法,先來個根據用戶名獲取角色的吧:

 /**
     * 獲取用戶及對應的角色信息
     *
     * @Author ZHANGCHAO
     * @Date 2020/3/4 11:03
     * @param
     * @retrun
     **/
    @GetMapping("/getUserRoles")
    public ResponseMessage getUserAndRolesByUserCode(@RequestParam("userName") String userName){
        SysUser user = (SysUser) userService.getOne(new QueryWrapper<SysUser>().lambda().eq(SysUser::getUserName,userName)).getData();
        if (isEmpty(user)){
            return new ResponseMessage(false,"用戶不存在!",null);
        }
        List<SysUserRole> userRoles = (List<SysUserRole>) userRoleService.list(new QueryWrapper<SysUserRole>().lambda().eq(SysUserRole::getUserId,user.getId())).getData();
        List<SysRole> roleList = new ArrayList<>();
        if (isNotEmpty(userRoles)){
            userRoles.forEach(sysUserRole -> {
                roleList.add((SysRole) roleService.getById(sysUserRole.getRoleId()).getData());
            });
        }
        user.setRoles(roleList);
        return new ResponseMessage(true,user);
    }

postman測試:

image-20200319210248101

很好,完美!返回了用戶名是zhangchao的所有角色!😄爽歪歪,繼續再加個用戶吧:

/**
     * 新增用戶
     *
     * @Author ZHANGCHAO
     * @Date 2020/3/3 10:58
     * @param
     * @param user
     * @retrun com.junya.util.result.ResponseMessage
     **/
    @PostMapping("/addUser")
    public ResponseMessage saveUser(@RequestBody SysUser user){
        System.out.println(user);
        user.setPassword(new BCryptPasswordEncoder().encode(user.getPassword()));
        return userService.save(user);
    }

postman調用,竟然返回登錄頁面的HTML:

image-20200319210700305

懷疑是不是找不到接口?!換成GET方式調用試試:

image-20200319210851549

Request method 'GET' not supported說明方法沒問題,可以調用到。

經過查詢資料可知,Spring Security默認開啓CSRF防護:

spring security CSRF防護

CSRF是指跨站請求僞造(Cross-site request forgery),是web常見的攻擊之一。
從Spring Security 4.0開始,默認情況下會啓用CSRF保護,以防止CSRF攻擊應用程序,Spring Security CSRF會針對PATCH,POST,PUT和DELETE方法進行防護。
我這邊是spring boot項目,在啓用了@EnableWebSecurity註解後,CSRF保護就自動生效了。
所以在默認配置下,即便已經登錄了,頁面中發起PATCH,POST,PUT和DELETE請求依然會被拒絕,並返回403,需要在請求接口的時候加入CSRF Token纔行。

image-20200319211901774

原來如此,那就在項目的配置中先禁用掉吧:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests() //需要授權的請求
                .antMatchers("/login","/home","/getCode").permitAll() //過濾不需要認證的路徑
                .antMatchers("/auth/**").permitAll() //過濾不需要認證的路徑
                .anyRequest().authenticated() //對任何一個請求,都需要認證
                .and() //完成上一個配置,進行下一步配置
                //.httpBasic();
                .formLogin() //配置表單登錄
                .loginPage("/login") //設置登錄頁面
                .successHandler(successHandler)  /* 設置成功處理器 */
                .failureHandler(failureHandler)  /* 設置失敗處理器*/
                .and()
                .logout() //登出
                .logoutSuccessUrl("/home"); //設置退出頁面
        // 添加驗證碼過濾器
        http.addFilterBefore(verifyCodeFilter, UsernamePasswordAuthenticationFilter.class);
        // 禁用CSRF防護
        http.csrf().disable();
    }

很簡單,加上http.csrf().disable()即可。

重啓項目,postman測試下:

image-20200319212240962

OK,很好,已經添加到數據庫中了!😆😆😆

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章