我尝试在我的应用程序中实现SAML,该应用程序由SPA(Flutter Web)和REST API(Springboot)组成,但在实现Flutter前端应用程序、Springboot Rest API和SAML身份提供者之间的通信时遇到了问题。
目前我已经实现了一个初始HTTP请求(@GetMapping(“/initial”)),在Flutter应用程序启动时调用,它检查是否配置了SAML,然后将Authentication Post请求发送到身份提供者。我的问题是身份提供者将Rest API应答到RestController中的另一个PostMap(@PostMapping(“samlsso”).然后,我为经过身份验证的用户生成一个Bearer Token,传递给Flutter应用程序,以处理应用程序中的身份验证状态并自动让用户登录。
但是我如何将这个令牌传递给Flutter应用程序呢?因为我使用的是REST控制器,所以我不应该在控制器中保存任何变量,但是为了让Flutter应用程序从Rest API接收数据,它必须发送一个令牌请求。但是Flutter应用程序不知道,当令牌准备好接收时,我如何正确地实现这个通信,而不需要任何手动延迟,并将值保存在RestController类的变量中?
PS:我已经尝试过从接收和处理SAML响应的PostMapping直接向前端发送响应。重定向,但我只能通过头部发送,无法从Flutter应用程序访问它。
后端代码:
@RestController
class SamlController {
var samlToken = ""
@GetMapping("/initial")
fun findToken() {
sendAuthRequestToIdp()
}
@PostMapping("/samlsso")
fun findAll(request: HttpServletRequest, response: HttpServletResponse) {
val user = receiveAndHandleIDPResponse()
//handle errors
val token = generateTokenFromIDPResponse()
samlToken = token
}
@PostMapping("/getSamlToken")
fun findAll(): ResponseEntity<String> {
return ResponseEntity.ok(samlToken)
}
}
前端代码:
Future<String> fetchSamlAuthentication () async {
var jwtString = '';
await launch("api_url/initial"); // launch, so that the IDP website opens in the browser
await Future.delayed(const Duration(milliseconds: 10000));//wait manually until token has been generated
final response = await _client.post(Uri.parse("api_url/getSamlToken"), headers: headers);
jwtString = response.body;
return jwtString;
}
这是我能够使用SAML验证用户身份的唯一方法,但它不是一个干净/可用的解决方案。我需要一个更好的方法来将生成的令牌发送到Flutter应用程序并能够处理它。
1条答案
按热度按时间scyqe7ek1#
SAML 2.0基于浏览器;IdP对用户进行身份验证后,IdP将 * 通过浏览器 * 向应用后端发送SAML响应。这可能是您问题中对
POST /samlsso
的调用。然后,应用的后端应验证SAML响应,例如检查SAML响应中包含的任何签名是否有效,前提是IdP的SAML元数据已在之前设置SAML连接时获得。
验证完成后,应用的后端应通过发送重定向响应来完成
POST /samlsso
,其中包含一个令牌或cookie,表明用户已通过身份验证。如何完成将取决于您的前端,尤其是它是否基于浏览器。在您的情况下,由于您的应用前端在浏览器中运行,并且您希望对后续请求使用承载令牌(而不是会话Cookie),因此您可以将令牌包含在重定向到的URL中,该URL应该是Flutter应用中的一个路由。
当你的Flutter应用重新加载时,它可以从URL中检索令牌,并通过每个请求的授权头在后续API调用中传递它。希望你的不记名令牌在创建时已经由后端签名,以便后端在服务后续请求时可以验证它是合法获得的。