英文:
AWS Cognito logout using spring security logoutSuccessHandler
问题
以下是要翻译的内容:
我在注销功能(与AWS Cognito集成)方面遇到了问题,希望有人能帮助我找出根本原因。我的要求是,一旦用户点击注销并使会话无效,就将用户重定向回登录界面,并提示输入用户名和密码。但是,当我点击注销链接时,由于重定向的发生,我遇到了以下错误。
(index):1 对'https://incatalyst.auth.us-east-1.amazoncognito.com/logout?client_id=******&redirect_uri=http://localhost:8080/login/oauth2/code/cognito&response_type=code&scope=openid&state=STATE' 的 XMLHttpRequest 访问(从'http://localhost:8080/logout' 重定向)已被 CORS 策略阻止:预检请求的响应未能通过访问控制检查:在所请求的资源上没有'Access-Control-Allow-Origin' 标头。
jquery.js:8623 GET https://incatalyst.auth.us-east-1.amazoncognito.com/logout?client_id=39ebrskq9ne4ib97466cav9fpf&redirect_uri=http://localhost:8080/login/oauth2/code/cognito&response_type=code&scope=openid&state=STATE net::ERR_FAILED
package com.example;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.HttpStatus;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
@SpringBootApplication
@RestController
public class SocialApplication extends WebSecurityConfigurerAdapter {
@Autowired
CustomizeLogoutSuccessHandler customizeLogoutSuccessHandler;
@RequestMapping("/user")
public Map<String, Object> user(@AuthenticationPrincipal OAuth2User principal) {
System.out.println(principal);
return Collections.singletonMap("name", principal.getAttribute("name"));
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests(a -> a
.antMatchers("/", "/logout", "/error", "/webjars/**").permitAll()
.anyRequest().authenticated()
)
.exceptionHandling(e -> e
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
)
.csrf(c -> c
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
)
.logout(l -> l
.logoutSuccessHandler(customizeLogoutSuccessHandler).permitAll()
)
.oauth2Login();
// @formatter:on
}
public static void main(String[] args) {
SpringApplication.run(SocialApplication.class, args);
}
}
以下是我的 CustomizeLogoutSuccessHandler:
package com.example;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;
@Component
public class CustomizeLogoutSuccessHandler implements LogoutSuccessHandler {
@Override
public void onLogoutSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
// 业务代码在这里
// System.out.println("Logout Sucessfull with Principal: " + authentication.getName());
Cookie awsCookie = new Cookie("AWSELBAuthSessionCookie-0", "deleted");
awsCookie.setMaxAge(-1);
awsCookie.setPath("/");
response.addCookie(awsCookie);
request.getSession().invalidate();
// 重定向到登录页面
response.sendRedirect("https://incatalyst.auth.us-east-1.amazoncognito.com/logout?client_id=*****&redirect_uri=http://localhost:8080/login/oauth2/code/cognito&response_type=code&scope=openid&state=STATE");
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate, max-age=0");
response.setHeader("Pragma", "no-cache");
response.setHeader("Access-Control-Allow-Origin","*");
response.setHeader("Access-Control-Allow-Headers","Origin, Content-Type, X-Auth-Token");
response.setHeader("Access-Control-Allow-Methods","GET");
response.setDateHeader("Expires", -1);
}
}
HTML 代码:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Demo</title>
<meta name="description" content="" />
<meta name="viewport" content="width=device-width" />
<base href="/" />
<link rel="stylesheet" type="text/css"
href="/webjars/bootstrap/css/bootstrap.min.css" />
<script type="text/javascript" src="/webjars/jquery/jquery.min.js"></script>
<script type="text/javascript"
src="/webjars/bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
<h1>Login</h1>
<div class="container unauthenticated">
With Cognito: <a href="/oauth2/authorization/cognito">click here</a>
</div>
<div class="container authenticated" style="display: none">
Logged in as: <span id="user"></span>
<div>
<button onClick="logout()" class="btn btn-primary">Logout</button>
</div>
</div>
<script type="text/javascript"
src="/webjars/js-cookie/js.cookie.js"></script>
<script type="text/javascript">
$
.ajaxSetup({
beforeSend : function(xhr, settings) {
if (settings.type == 'POST' || settings.type == 'PUT'
|| settings.type == 'DELETE') {
if (!(/^http:.*/.test(settings.url) || /^https:.*/
.test(settings.url))) {
// 仅将令牌发送到相对URL,即本地URL。
xhr.setRequestHeader("X-XSRF-TOKEN",
Cookies.get('XSRF-TOKEN'));
}
}
}
});
$.get("/user", function(data) {
$("#user").html(data.name);
$(".unauthenticated").hide();
$(".authenticated").show();
});
var logout = function() {
<details>
<summary>英文:</summary>
I face an issue with the logout functionality(integrate with AWS Cognito), I hope someone will help me in identifying the root cause. My requirement is to redirect the user back to the login screen and prompt for username and password once the user clicks on logout and invalidate the session. But I am getting these errors while I click on the logout link because of the redirection happening.
----------
(index):1 Access to XMLHttpRequest at 'https://incatalyst.auth.us-east-1.amazoncognito.com/logout?client_id=******&redirect_uri=http://localhost:8080/login/oauth2/code/cognito&response_type=code&scope=openid&state=STATE' (redirected from 'http://localhost:8080/logout') from origin 'http://localhost:8080' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
jquery.js:8623 GET https://incatalyst.auth.us-east-1.amazoncognito.com/logout?client_id=39ebrskq9ne4ib97466cav9fpf&redirect_uri=http://localhost:8080/login/oauth2/code/cognito&response_type=code&scope=openid&state=STATE net::ERR_FAILED
package com.example;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.HttpStatus;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
@SpringBootApplication
@RestController
public class SocialApplication extends WebSecurityConfigurerAdapter {
@Autowired
CustomizeLogoutSuccessHandler customizeLogoutSuccessHandler;
@RequestMapping("/user")
public Map<String, Object> user(@AuthenticationPrincipal OAuth2User principal) {
System.out.println(principal);
return Collections.singletonMap("name", principal.getAttribute("name"));
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests(a -> a
.antMatchers("/","/logout", "/error", "/webjars/**").permitAll()
.anyRequest().authenticated()
)
.exceptionHandling(e -> e
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
)
.csrf(c -> c
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
)
.logout(l -> l
.logoutSuccessHandler(customizeLogoutSuccessHandler).permitAll()
)
.oauth2Login();
// @formatter:on
}
public static void main(String[] args) {
SpringApplication.run(SocialApplication.class, args);
}
}
Below is my customizeLogoutSuccessHandler
package com.example;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;
@Component
public class CustomizeLogoutSuccessHandler implements LogoutSuccessHandler{
@Override
public void onLogoutSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
// Code For Business Here
// System.out.println("Logout Sucessfull with Principal: " + authentication.getName());
Cookie awsCookie = new Cookie("AWSELBAuthSessionCookie-0", "deleted");
awsCookie.setMaxAge(-1);
awsCookie.setPath("/");
response.addCookie(awsCookie);
request.getSession().invalidate();
//redirect to login
response.sendRedirect("https://incatalyst.auth.us-east-1.amazoncognito.com/logout?client_id=*****&redirect_uri=http://localhost:8080/login/oauth2/code/cognito&response_type=code&scope=openid&state=STATE");
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate, max-age=0");
response.setHeader("Pragma", "no-cache");
response.setHeader("Access-Control-Allow-Origin","*");
response.setHeader("Access-Control-Allow-Headers","Origin, Content-Type, X-Auth-Token");
response.setHeader("Access-Control-Allow-Methods","GET");
response.setDateHeader("Expires", -1);
}
}
HTML
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Demo</title>
<meta name="description" content="" />
<meta name="viewport" content="width=device-width" />
<base href="/" />
<link rel="stylesheet" type="text/css"
href="/webjars/bootstrap/css/bootstrap.min.css" />
<script type="text/javascript" src="/webjars/jquery/jquery.min.js"></script>
<script type="text/javascript"
src="/webjars/bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
<h1>Login</h1>
<div class="container unauthenticated">
With Cognito: <a href="/oauth2/authorization/cognito">click here</a>
</div>
<div class="container authenticated" style="display: none">
Logged in as: <span id="user"></span>
<div>
<button onClick="logout()" class="btn btn-primary">Logout</button>
</div>
</div>
<script type="text/javascript"
src="/webjars/js-cookie/js.cookie.js"></script>
<script type="text/javascript">
$
.ajaxSetup({
beforeSend : function(xhr, settings) {
if (settings.type == 'POST' || settings.type == 'PUT'
|| settings.type == 'DELETE') {
if (!(/^http:.*/.test(settings.url) || /^https:.*/
.test(settings.url))) {
// Only send the token to relative URLs i.e. locally.
xhr.setRequestHeader("X-XSRF-TOKEN",
Cookies.get('XSRF-TOKEN'));
}
}
}
});
$.get("/user", function(data) {
$("#user").html(data.name);
$(".unauthenticated").hide();
$(".authenticated").show();
});
var logout = function() {
$.post("/logout", function() {
$("#user").html('');
$(".unauthenticated").show();
$(".authenticated").hide();
})
return true;
}
</script>
</body>
</html>
</details>
专注分享java语言的经验与见解,让所有开发者获益!
评论