gpt4 book ai didi

spring-security - Spring Security OAuth2 AngularJS |注销流程

转载 作者:行者123 更新时间:2023-12-04 18:59:15 25 4
gpt4 key购买 nike

引用oauth2中的注销流程spring-guides 项目,一旦用户第一次使用用户/密码进行身份验证,下次注销后就不会询问凭据。

如何确保每次注销后都询问用户名/密码。

这就是我想要实现的:-

  • OAuth2 服务器使用“authorization_code”授权类型发布 JWT token
    自动批准。这有 html/angularjs 表单可以收集
    用户名密码。
  • UI/Webfront - 使用 @EnableSSO。它的所有端点都经过身份验证
    即它没有任何未经授权的登录页面/用户界面/该用户的链接
    单击以转到/uaa 服务器。所以打http://localhost:8080
    立即将您重定向到 http://localhost:9999/uaa和礼物
    自定义表单来收集用户名/密码。
  • 资源服务器 - 使用 @EnableResourceServer。简单明了的 REST api。

  • 使用上述方法,我无法锻炼注销流程。对 UI 应用程序的 HTTP POST/logout 会清除 UI 应用程序中的 session /身份验证,但用户会自动再次登录(因为我选择了对所有范围的自动批准),而不会再次被要求输入用户名密码。

    查看日志和网络调用,似乎所有的“oauth 舞蹈”都成功地再次发生,而没有再次要求用户输入用户名/密码,并且似乎 auth 服务器记得为客户端发出的最后一个 auth token (使用 org.springframework .security.oauth2.provider.code.InMemoryAuthorizationCodeServices?)。

    我如何告诉身份验证服务器在每次请求代码/ token 时询问用户名/密码 - 无状态。

    或者在我的给定场景中实现注销的最佳方法是什么。

    (要重新创建有点接近我的要求,请从 UiApplication 中删除 permitAll() 部分并在提到的启动项目的身份验证服务器中配置 autoApproval。)

    github issue

    最佳答案

    我也遇到了你描述的错误,我从问题中看到了一个解决方案
    Spring Boot OAuth2 Single Sign Off .我并不是说这是唯一的全局性真相解决方案。

    但在场景中,

  • 身份验证服务器具有登录表单,您已从中进行身份验证
  • 浏览器仍然保持与认证服务器的 session
  • 在您完成注销过程后(撤销 token ,删除 cookie...)
    并再次尝试重新登录
  • 认证服务器不发送登录表单并自动登录

  • 您需要从身份验证服务器的 session 中删除身份验证信息 this回答描述。

    下面的片段是我如何配置解决方案

    客户端(在您的情况下为 UI 应用程序)应用程序的 WebSecurityConfig
    ...
    @Value("${auth-server}/ssoLogout")
    private String logoutUrl;
    @Autowired
    private CustomLogoutHandler logoutHandler;
    ...
    @Override
    public void configure(HttpSecurity http) throws Exception {
    // @formatter:off
    http.antMatcher("/**")
    .authorizeRequests()
    .antMatchers("/", "/login").permitAll()
    .anyRequest().authenticated()
    .and()
    .logout()
    .logoutSuccessUrl(logoutUrl)
    .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
    .addLogoutHandler(logoutHandler)
    .and()
    .csrf()
    .csrfTokenRepository(csrfTokenRepository())
    .and()
    .addFilterAfter(csrfHeaderFilter(), CsrfFilter.class);
    // @formatter:on
    }

    客户端应用程序的自定义注销处理程序
    @Component
    public class CustomLogoutHandler implements LogoutHandler {

    private static Logger logger = Logger.getLogger(CustomLogoutHandler.class);

    @Value("${auth-server}/invalidateTokens")
    private String logoutUrl;

    @Override
    public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {

    logger.debug("Excution CustomLogoutHandler for " + authentication.getName());
    Object details = authentication.getDetails();
    if (details.getClass().isAssignableFrom(OAuth2AuthenticationDetails.class)) {

    String accessToken = ((OAuth2AuthenticationDetails) details).getTokenValue();
    RestTemplate restTemplate = new RestTemplate();

    MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
    params.add("access_token", accessToken);

    HttpHeaders headers = new HttpHeaders();
    headers.add("Authorization", "bearer " + accessToken);

    HttpEntity<Object> entity = new HttpEntity<>(params, headers);

    HttpMessageConverter<?> formHttpMessageConverter = new FormHttpMessageConverter();
    HttpMessageConverter<?> stringHttpMessageConverternew = new StringHttpMessageConverter();
    restTemplate.setMessageConverters(Arrays.asList(new HttpMessageConverter[] { formHttpMessageConverter, stringHttpMessageConverternew }));
    try {
    ResponseEntity<String> serverResponse = restTemplate.exchange(logoutUrl, HttpMethod.POST, entity, String.class);
    logger.debug("Server Response : ==> " + serverResponse);
    } catch (HttpClientErrorException e) {
    logger.error("HttpClientErrorException invalidating token with SSO authorization server. response.status code: " + e.getStatusCode() + ", server URL: " + logoutUrl);
    }
    }
    authentication.setAuthenticated(false);
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    new SecurityContextLogoutHandler().logout(request, response, auth);

    }

    }

    我使用了JDBC tokenStore,所以需要撤销tokens。在认证服务器端,我添加了一个 Controller 来处理注销过程
    @Controller
    public class AuthenticationController {

    private static Logger logger = Logger.getLogger(AuthenticationController.class);

    @Resource(name = "tokenStore")
    private TokenStore tokenStore;

    @Resource(name = "approvalStore")
    private ApprovalStore approvalStore;

    @RequestMapping(value = "/invalidateTokens", method = RequestMethod.POST)
    public @ResponseBody Map<String, String> revokeAccessToken(HttpServletRequest request, HttpServletResponse response, @RequestParam(name = "access_token") String accessToken, Authentication authentication) {
    if (authentication instanceof OAuth2Authentication) {
    logger.info("Revoking Approvals ==> " + accessToken);
    OAuth2Authentication auth = (OAuth2Authentication) authentication;
    String clientId = auth.getOAuth2Request().getClientId();
    Authentication user = auth.getUserAuthentication();
    if (user != null) {
    Collection<Approval> approvals = new ArrayList<Approval>();
    for (String scope : auth.getOAuth2Request().getScope()) {
    approvals.add(new Approval(user.getName(), clientId, scope, new Date(), ApprovalStatus.APPROVED));
    }
    approvalStore.revokeApprovals(approvals);
    }
    }
    logger.info("Invalidating access token :- " + accessToken);
    OAuth2AccessToken oAuth2AccessToken = tokenStore.readAccessToken(accessToken);
    if (oAuth2AccessToken != null) {
    if (tokenStore instanceof JdbcTokenStore) {
    logger.info("Invalidating Refresh Token :- " + oAuth2AccessToken.getRefreshToken().getValue());
    ((JdbcTokenStore) tokenStore).removeRefreshToken(oAuth2AccessToken.getRefreshToken());
    tokenStore.removeAccessToken(oAuth2AccessToken);
    }
    }
    Map<String, String> ret = new HashMap<>();
    ret.put("removed_access_token", accessToken);
    return ret;
    }

    @GetMapping("/ssoLogout")
    public void exit(HttpServletRequest request, HttpServletResponse response) throws IOException {
    new SecurityContextLogoutHandler().logout(request, null, null);
    // my authorization server's login form can save with remember-me cookie
    Cookie cookie = new Cookie("my_rememberme_cookie", null);
    cookie.setMaxAge(0);
    cookie.setPath(StringUtils.hasLength(request.getContextPath()) ? request.getContextPath() : "/");
    response.addCookie(cookie);
    response.sendRedirect(request.getHeader("referer"));
    }

    }

    在授权服务器的 SecurityConfig,您可能需要允许此 url 作为
    http
    .requestMatchers()
    .antMatchers(
    "/login"
    ,"/ssoLogout"
    ,"/oauth/authorize"
    ,"/oauth/confirm_access");

    我希望这可能对您有所帮助。

    关于spring-security - Spring Security OAuth2 AngularJS |注销流程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41850162/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com