将经过身份验证的用户保存到来自Azure AD的数据库中



我正在开发一个简单的web应用程序,用于学习目的,前端使用Angular,后端使用JavaSpring。我没有什么特别的问题需要你们帮我解决,相反,我有一个关于OAuth2身份验证的问题。

我已经在Azure AD(授权代码流+PKCE(中注册了我的Angular SPA,我设置了角色,一切都正常。我的问题是,当经过身份验证的用户ping我的后端时,我该怎么办?我的后端没有关于用户的信息。

我想了一个解决方案来制作一个网络过滤器,每次经过身份验证的用户ping任何需要对用户进行身份验证的端点时,都会检查数据库中是否存在该用户(通过用户名(,如果不存在则保存该用户。我很确定这会起作用,但我不认为这是最好的解决方案,因为我的网络过滤器必须从数据库中读取每个传入的HTTP请求,并偶尔写入数据库(如果用户是第一次登录(。

我不应该担心性能问题,因为我建立这个系统完全是为了学习,但尽管如此,我还是想以正确的方式做到这一点。我试着用多种方式在谷歌上搜索,但我想我没有用正确的关键词来找到我想要的东西。任何意见或建议都将不胜感激!谢谢

编辑:我遵循这篇文章实现了OAuth2+OIDC身份验证和授权,我在后端的安全配置是一样的:https://ordina-jworks.github.io/security/2020/08/18/Securing-Applications-Azure-AD.html

发布关于需求的清晰讨论。如果你想使用有以下:

  • 接受Azure AD登录用户使用您的web服务
  • 您需要检查用户是否存在于您的应用程序数据库中,并且网络延迟最小

对于不总是访问数据库的要求,一种选择是使用缓存。

此缓存工作的理想解决方案是:

  • 确保使用Web筛选器检查每个HTTP请求的缓存
  • 确保缓存始终使用通过Azure AD登录的最新用户进行更新

示例:

实现CacheService.java

package com.example.springboot;
import java.util.Collections;
import org.apache.catalina.User;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Component
public class CacheService {
@Bean
public CacheManager cacheManager() {
SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.setCaches(Collections.singletonList(new ConcurrentMapCache("users")));
return cacheManager;
}

@Cacheable(cacheNames = "users")
public User getUser(String username) {
// Code below will not execute after the first calling for the given username. 
// So if one username is already cached, it would not invoke for the same user again from the DB.
// Get or Create a new user based on the Database call
return null;
}
}

然后实现一个web过滤器,如:

package com.example.springboot;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.GenericFilterBean;
@Component
public class CredentialsInjectionFilter extends GenericFilterBean {
@Autowired
private CacheService cacheService;
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
cacheService.getUser("my_username");
filterChain.doFilter(servletRequest, servletResponse);
}
}

有关使用Springboot缓存的更多信息:https://www.javadevjournal.com/spring/spring-caching/

最新更新