User must be authenticated with Spring Security before authorization can be completed.異常處理

錯(cuò)誤:User must be authenticated with Spring Security before authorization can be completed.

簡(jiǎn)要說(shuō)下錯(cuò)誤原因:
該錯(cuò)誤是oauth2 授權(quán)碼模式 訪問(wèn)接口 /oauth/authorize 時(shí)仪召,由于SpringSecurity上下文中沒(méi)有用戶(hù)認(rèn)證信息曙搬,所以在spring security 中攔截報(bào)錯(cuò)。源碼中 在/oauth/authorize 接口debug可以看到問(wèn)題端蛆。

處理方法
錯(cuò)誤信息已經(jīng)說(shuō)明了是要先認(rèn)證秉氧,所以我們?cè)谡?qǐng)求/oauth/authorize接口前認(rèn)證用戶(hù)信息即可

1.1 通過(guò)寫(xiě)一個(gè)用戶(hù)身份過(guò)濾器進(jìn)行處理掖看,代碼如下


@Component
@Slf4j
public class TokenAuthenticationFilter extends OncePerRequestFilter {

    @Autowired
    AuthenticationManager authenticationManager;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
        String token = request.getHeader(HttpConstant.Header.AUTHENTICATION);
        if (StrUtil.isBlank(token)) {
            //解析請(qǐng)求參數(shù) request.getQueryString()
            Map<String, String> parameters = HttpParamUtil.getRequestParameters(request);
            if (SecurityConstants.AUTH_CODE_URL.equals(request.getRequestURI())&&parameters.size()>0) {
                //參數(shù)中提取 clientId 捕发,根據(jù)client 數(shù)據(jù)庫(kù)查詢(xún)用戶(hù)信息進(jìn)行身份認(rèn)證
                String clientId = parameters.get("client_id");
                //根據(jù)clientId查詢(xún)用戶(hù)信息 省略數(shù)據(jù)庫(kù)用戶(hù)信息查詢(xún)
                String  username="admin";
                String password="123456";
                //賬號(hào)密碼認(rèn)證
                JwtAuthenticationToken jwtAuthenticationToken = new JwtAuthenticationToken(username, password);
                // 通過(guò)authenticationManager
                Authentication authentication = authenticationManager.authenticate(jwtAuthenticationToken);
                // 認(rèn)證成功后將認(rèn)證信息存儲(chǔ)到SpringSecurity上下文中
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
            filterChain.doFilter(request, response);
            //在過(guò)濾器中添加return锁右,是為了結(jié)束該方法的運(yùn)行失受,也就是結(jié)束過(guò)濾
            return;
        }
    }
}

方法邏輯說(shuō)明:用戶(hù)請(qǐng)求中沒(méi)有認(rèn)證令牌token,判斷請(qǐng)求路徑是否是/oauth/authorize,如果是同時(shí)判斷是否攜帶有參數(shù)(攜帶參數(shù)是請(qǐng)求授權(quán)的請(qǐng)求咏瑟,生成授權(quán)碼的請(qǐng)求沒(méi)有參數(shù))拂到,如果有則解析參數(shù)獲取cliend_id,根據(jù)cliend_id 查詢(xún)數(shù)據(jù)庫(kù)該用戶(hù)信息码泞,完成spring security 的鑒權(quán)并將認(rèn)證信息息存儲(chǔ)到SpringSecurity上下文中

1.2 spring security 核心配置類(lèi)中 注冊(cè)以上的過(guò)濾器兄旬,并指定該過(guò)濾器為spring security 一系列過(guò)濾器的首個(gè)過(guò)濾器
1.3 spring security 核心配置類(lèi)中 對(duì) 以 /oauth 開(kāi)頭的請(qǐng)求放行


@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private MyLogOutSuccessHandler logOutSuccessHandler;
    @Autowired
    private SimpleAccessDeniedHandler simpleAccessDeniedHandler;
    @Autowired
    private SimpleAuthenticationEntryPoint simpleAuthenticationEntryPoint;
    @Autowired
    private TokenAuthenticationFilter tokenAuthenticationFilter;

    /**
     * http請(qǐng)求攔截認(rèn)證
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 禁用 csrf, 由于使用的是JWT,我們這里不需要csrf
        http.csrf().disable();
        http.authorizeRequests()
                .and()
                .formLogin() //新增login form支持用戶(hù)登錄及授權(quán)
                //自定義登錄頁(yè)面
                .loginPage("http://localhost:3000/login")
                //認(rèn)證成功跳轉(zhuǎn)的頁(yè)面
                .successForwardUrl("http://localhost:3000/index")
                .failureForwardUrl("http://localhost:3000/login")
                .and()
                .logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("http://localhost:3000/login")
                .logoutSuccessHandler(logOutSuccessHandler)
                .permitAll()

                //wagger 相關(guān)請(qǐng)求放行
                .and()
                .authorizeRequests()
                //oauth相關(guān)請(qǐng)求放行
                .antMatchers("/oauth/**").permitAll()
                .antMatchers("/login/**").permitAll()
                .antMatchers("/logout/**").permitAll()
                .antMatchers("/swagger-ui.html").permitAll()
                .antMatchers("/swagger-resources").permitAll()
                .antMatchers("/swagger-ui/*").permitAll()
                .antMatchers("/v2/api-docs").permitAll()
                .antMatchers("/v3/api-docs").permitAll()
                .antMatchers("/webjars/**").permitAll()

                // 其他所有請(qǐng)求需要身份認(rèn)證
                .anyRequest().authenticated()

                //配置自定義異常處理
                .and().exceptionHandling()
                .accessDeniedHandler(simpleAccessDeniedHandler)
                .authenticationEntryPoint(simpleAuthenticationEntryPoint);

        // 添加自定義  過(guò)濾器  余寥,放置在身份認(rèn)證過(guò)濾器前
        http.addFilterBefore(tokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
    }


    @Override
    protected void configure(AuthenticationManagerBuilder auth) {
        // 使用自定義登錄身份認(rèn)證組件
        auth.authenticationProvider(new JwtAuthenticationProvider(userDetailsService));
    }


    /**
     * AuthenticationManager對(duì)象在OAuth2認(rèn)證服務(wù)中要使用领铐,提前放入IOC容器中
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市宋舷,隨后出現(xiàn)的幾起案子绪撵,更是在濱河造成了極大的恐慌,老刑警劉巖祝蝠,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件音诈,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡绎狭,警方通過(guò)查閱死者的電腦和手機(jī)细溅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)儡嘶,“玉大人喇聊,你說(shuō)我怎么就攤上這事”目瘢” “怎么了承疲?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵邻耕,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我燕鸽,道長(zhǎng)兄世,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任啊研,我火速辦了婚禮御滩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘党远。我一直安慰自己削解,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布沟娱。 她就那樣靜靜地躺著氛驮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪济似。 梳的紋絲不亂的頭發(fā)上矫废,一...
    開(kāi)封第一講書(shū)人閱讀 51,125評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音砰蠢,去河邊找鬼蓖扑。 笑死,一個(gè)胖子當(dāng)著我的面吹牛台舱,可吹牛的內(nèi)容都是我干的律杠。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼竞惋,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼柜去!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起拆宛,我...
    開(kāi)封第一講書(shū)人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤嗓奢,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后胰挑,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蔓罚,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡椿肩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年瞻颂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片郑象。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡贡这,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出厂榛,到底是詐尸還是另有隱情盖矫,我是刑警寧澤丽惭,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站辈双,受9級(jí)特大地震影響责掏,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜湃望,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一换衬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧证芭,春花似錦瞳浦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至官硝,卻和暖如春矗蕊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背泛源。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工拔妥, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人达箍。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓没龙,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親缎玫。 傳聞我的和親對(duì)象是個(gè)殘疾皇子硬纤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容