关于异常处理以及针对spring security oauth 2的401错误进行页面跳转

SpringBoot错误集中处理与OAuth2认证问题
本文介绍如何在SpringBoot项目中配置错误集中处理,包括404、500等HTTP状态码的自定义页面显示,以及解决OAuth2认证中invalid_token问题的方法。通过实现ErrorPageConfig和AuthExceptionEntryPoint,实现对特定错误的统一处理。

由于最近遇到了新问题,还折磨了我两天,所以这里就简单的记录一下⑧

错误集中处理

由于系统需要,所以为项目添加了一个错误集中处理配置
前情提要

spring boot : 2.0.3.RELEASE

参考文章

首先根据spring boot版本的不同,以1.4.0为界是有不同的配置方式的,这里由于用的是2.0.3.RELEASE,所以配置如下。

package com.yubotao.springsecurityoauth2.config;

import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.ErrorPageRegistrar;
import org.springframework.boot.web.server.ErrorPageRegistry;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;



/**
 * @Auther: yubt
 * @Description:
 * @Date: Created in 17:23 2018/10/10
 * @Modified By:
 */
@Component
public class ErrorPageConfig implements ErrorPageRegistrar {

    @Override
    public void registerErrorPages(ErrorPageRegistry registry){
        ErrorPage[] errorPages = new ErrorPage[]{
                new ErrorPage(HttpStatus.NOT_FOUND, "/error/404"),
                new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500"),
                new ErrorPage(Throwable.class, "/error/500")
        };
        registry.addErrorPages(errorPages);

    }

}

接着加一个进行跳转的Controller

package com.yubotao.springsecurityoauth2.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * @Auther: yubt
 * @Description:
 * @Date: Created in 17:17 2018/10/10
 * @Modified By:
 */
@Controller
@RequestMapping("/error")
public class ErrorController {

    @RequestMapping(value = "/401", method = RequestMethod.GET)
    public String error_401(){
        return "error_401";
    }

    @RequestMapping(value = "/404", method = RequestMethod.GET)
    public String error_404(){
        return "error_404";
    }

    @RequestMapping(value = "/500", method = RequestMethod.GET)
    public String error_500(){
        return "error_500";
    }

}

然后放一个页面吧,其他的都一样
error_404.html

<!DOCTYPE html>
<html>
<head>

</head>

<body>
<h1>404</h1>
<h3>抱歉,无法找到网页</h3>
</body>
</html>

spring security oauth 2 的401处理(invalid_token)

开始我们使用了上面的那种异常集中处理,我开始以为可以把401错误也纳入其中,但是经过尝试之后发现这种方式是行不通的,因为当出现401报错的时候,返回的是一个xml形式的,总之就很烦,然后这个地方我用了1天的时间才找到比较好的解决办法。
在这里插入图片描述

最开始的想法是用过滤器,应该是可以做的,但是我没做,一个是网上相关资料较少,再就是想看看有没有其他的方式解决。

后来用尝试了使用对oauth 2的资源服务器进行配置登陆页面的方式,就是如下这种方式

 @Override
        public void configure(HttpSecurity http) throws Exception {
            // @formatter:off
            http
                    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
                    .and()
                    .requestMatchers().anyRequest()
                    .and()
                    .anonymous()
                    .and()
                    .formLogin().loginPage("/login")
                    .and()
                    .authorizeRequests()
                    // or可以通过access_token访问,但是and不行;经过测试,应该是hasRole()方法出了问题,这里无法通过
//                    .antMatchers("/product/**").access("#oauth2.hasScope('select') and  hasRole('ROLE_ADMIN')")
                    .antMatchers("/order/**").authenticated();  // 配置order访问控制,必须认证过后才可以访问
            // @formatter:on
        }

这种情况貌似是失败了,无奈之下,只能继续寻找解决方法,果然让我找到了,可以看到这个文章,虽然效果不是我想要的,但是是可以借鉴的。

所以其实我们只需要定义一个AuthExceptionEntryPoint

package com.yubotao.springsecurityoauth2.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @Auther: yubt
 * @Description:
 * @Date: Created in 11:36 2018/10/11
 * @Modified By:
 */
public class AuthExceptionEntryPoint implements AuthenticationEntryPoint {

    @Value("${server.url}")
    private  String serverUrl;

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
                         AuthenticationException authException)
            throws ServletException {

//        Map map = new HashMap();
//        map.put("error", "401");
//        map.put("message", "token过期,请重新登陆");
//        map.put("path", request.getServletPath());
//        map.put("timestamp", String.valueOf(new Date().getTime()));
//        response.setContentType("application/json");
//        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);

        try {
//            ObjectMapper mapper = new ObjectMapper();
//            mapper.writeValue(response.getOutputStream(), map);
            System.out.println("进入Entry方法");
            response.sendRedirect(serverUrl + "/error/401");
        } catch (Exception e) {
            throw new ServletException();
        }
    }

}

开始的时候我以为这种方式也不行,因为我没有注掉那些代码,就进行了重定向,结果还是报错了,并且发现这个方法进入了两次,然后同事说了依据可能是response.setContentType("application/json");这句的问题,然后我就把上面的代码注掉,果然就可以正确重定向了。

这样,我们就把这个invalid_token的问题给解决了。
效果如下
当我请求http://localhost:8080/order/1时,由于需要权限,但是我并没有登陆,所以就会重定向到这个页面
在这里插入图片描述

而关于AuthenticationEntryPoint的相关文章,我只能找到这样一篇文章,稍微提到了一下,也没去官方文档去查,不过大概了解它的功能了,就是一个认证系统,不过还是存疑,以后有机会可以再去官方文档搜搜。

赶着下班,今天就草草写到这了。

Github项目地址

<think>好的,我需要帮助用户解决在使用Spring SecurityOAuth2集成后如何跳转回用户登录前页面的问题。首先,我得理解用户的需求。用户希望在完成OAuth2认证之后,能够自动重定向到他们最初尝试访问的页面,而不是默认的某个固定页面。这在单点登录(SSO)场景中很常见,比如用户点击某个需要认证的资源,被重定向到登录页面,登录后应该回到原来的页面。 接下来,我需要回忆Spring SecurityOAuth2的相关机制。通常,Spring Security在用户未认证时会将他们重定向到登录页面,并在登录成功后根据配置跳转到默认的成功页面。但用户希望的是回到之前的页面,这通常涉及到保存请求前的URL。 根据引用内容,用户提到的@EnableOAuth2Sso注解和授权码生成流程可能相关。在OAuth2的流程中,当用户尝试访问受保护的资源时,会被重定向到授权服务器进行认证。认证成功后,需要能够返回到原来的请求页面。这时候可能需要配置Spring Security来保存请求前的URL,并在认证完成后进行重定向。 查看引用[4]提到的单点登录案例,里面可能涉及到如何配置OAuth2客户端和资源服务器,以及处理认证后的重定向。通常,这需要设置一个AuthenticationSuccessHandler,在认证成功时处理重定向逻辑。例如,使用SavedRequestAwareAuthenticationSuccessHandler,这个类会记住用户之前的请求,并在登录成功后重定向到那个URL。 另外,引用[3]中提到的AuthorizationEndpoint和授权码生成流程可能涉及到如何生成回调URL,其中可能需要包含原始请求的信息。不过这可能更多是在授权服务器端的配置,而用户的问题可能是在客户端如何处理回调后的重定向。 需要检查客户端的配置,确保在OAuth2客户端配置中正确设置了redirect_uri,并且服务器端允许这个URI。同时,在Spring Security的配置中,可能需要覆盖默认的认证成功处理逻辑,使用保存请求的Handler。 可能的步骤包括: 1. 配置Spring SecurityOAuth2客户端,正确设置redirect_uri。 2. 使用SavedRequestAwareAuthenticationSuccessHandler作为认证成功处理器,这样在认证成功后会自动跳转到之前保存的请求页面。 3. 确保在安全配置中允许保存请求,例如通过http.securityContext().and().authorizeRequests()...等配置。 同时,需要注意Spring Security OAuth2的版本差异,特别是Spring Boot 2.x之后的一些变化,如引用[1]提到的需要添加spring-security-oauth2-autoconfigure依赖才能使用@EnableOAuth2Sso注解。如果用户使用的是较新版本,可能需要调整配置方式,因为Spring官方已经将OAuth2的支持迁移到Spring Security 5.x的体系中,可能不再推荐使用@EnableOAuth2Sso,而是采用更现代的配置方式。 另外,引用[2]提到了资源服务器的依赖配置,这可能和客户端配置相关,但用户的问题更关注客户端认证后的重定向,因此资源服务器的配置可能不是重点,但需要确保整体依赖正确。 总结来说,用户需要在客户端应用中配置认证成功后的处理逻辑,使用Spring Security提供的机制来保存和恢复用户原始的请求URL。这通常可以通过自定义WebSecurityConfigurerAdapter,设置successHandler为SavedRequestAwareAuthenticationSuccessHandler来实现。同时,需要确保OAuth2客户端的回调URL正确配置,以处理授权服务器返回后的重定向。 可能还需要处理一些特殊情况,例如当用户直接访问登录页面而不是通过访问受保护资源触发的登录,这时候可能需要一个默认的重定向路径。此外,需要确保Session管理正确,以便保存用户的原始请求信息。 最后,可能需要参考Spring SecurityOAuth2的官方文档,以及相关的示例代码,来验证配置的正确性,并处理可能出现的异常情况,比如无效的redirect_uri或者会话过期等。</think>要实现Spring SecurityOAuth2集成后跳转回用户登录前的页面,需通过以下步骤配置: ### 1. 配置`SavedRequestAwareAuthenticationSuccessHandler` 在Spring Security配置类中,自定义认证成功处理器`SavedRequestAwareAuthenticationSuccessHandler`,它会自动记录用户访问的原始URL并在登录后重定向到该地址。 ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/", "/public/**").permitAll() .anyRequest().authenticated() .and() .oauth2Login() .successHandler(savedRequestSuccessHandler()) // 关键配置 .and() .logout().permitAll(); } private AuthenticationSuccessHandler savedRequestSuccessHandler() { SavedRequestAwareAuthenticationSuccessHandler handler = new SavedRequestAwareAuthenticationSuccessHandler(); handler.setDefaultTargetUrl("/"); // 设置默认跳转路径(可选) return handler; } } ``` ### 2. 确保OAuth2客户端回调地址正确 在`application.yml`中配置OAuth2客户端的`redirect-uri`,需与授权服务器注册的回调地址一致。例如: ```yaml spring: security: oauth2: client: registration: github: client-id: your-client-id client-secret: your-client-secret redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}" ``` ### 3. 验证会话管理 确保应用支持Session存储,Spring Security默认通过Session保存用户请求信息。若使用分布式Session(如Redis),需添加相关依赖并配置: ```xml <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency> ``` ### 原理解析 - **保存原始请求**:当未认证用户访问受保护资源时,Spring Security会通过`ExceptionTranslationFilter`将请求存入`RequestCache`(默认使用`HttpSessionRequestCache`),并触发OAuth2登录流程[^4]。 - **回调处理**:OAuth2登录成功后,`SavedRequestAwareAuthenticationSuccessHandler`会从`RequestCache`中读取原始请求地址并重定向。
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值