我正在使用Spring Boot、Spring Security性和spring会话(redis)构建spring REST web应用程序。我正在使用SpringCloud和zuul代理按照网关模式构建一个云应用程序。在这个模式中,我使用spring会话来管理redis中的HttpSession,并使用它来授权我的资源服务器上的请求。当执行更改会话权限的操作时,我希望更新该对象,以便用户不必注销以反映更新。有人能解决这个问题吗?
要更新权限,您需要在两个地方修改身份验证对象。一个在安全上下文中,另一个在请求上下文中。您的主体对象将是org.springframework.security.core.userdetails.User或扩展该类(如果您已重写UserDetailsService)。这适用于修改当前用户。
Authentication newAuth = new UsernamePasswordAuthenticationToken({YourPrincipalObject},null,List<? extends GrantedAuthority>)
SecurityContextHolder.getContext().setAuthentication(newAuth);
RequestContextHolder.currentRequestAttributes().setAttribute("SPRING_SECURITY_CONTEXT", newAuth, RequestAttributes.SCOPE_GLOBAL_SESSION);
要使用任何已登录用户的Spring会话更新会话,需要自定义过滤器。过滤器存储一组已被某个进程修改的会话。当需要修改新会话时,消息传递系统会更新该值。当请求具有匹配的会话密钥时,过滤器会在数据库中查找用户以获取更新。然后更新会话上的SPRING_SECURITY_CONTEXT属性,并更新SecurityContextHolder中的身份验证。用户不需要注销。当指定过滤器的顺序时,它必须位于SpringSessionRepositoryFilter之后。那个对象有一个@-2147483598,所以我只是改变了我的过滤器,以确保它是下一个被执行的。
工作流程如下所示:
>
下次用户A通过过滤器时,更新其会话
@Component
@Order(UpdateAuthFilter.ORDER_AFTER_SPRING_SESSION)
public class UpdateAuthFilter extends OncePerRequestFilter
{
public static final int ORDER_AFTER_SPRING_SESSION = -2147483597;
private Logger log = LoggerFactory.getLogger(this.getClass());
private Set<String> permissionsToUpdate = new HashSet<>();
@Autowired
private UserJPARepository userJPARepository;
private void modifySessionSet(String sessionKey, boolean add)
{
if (add) {
permissionsToUpdate.add(sessionKey);
} else {
permissionsToUpdate.remove(sessionKey);
}
}
public void addUserSessionsToSet(UpdateUserSessionMessage updateUserSessionMessage)
{
log.info("UPDATE_USER_SESSION - {} - received", updateUserSessionMessage.getUuid().toString());
updateUserSessionMessage.getSessionKeys().forEach(sessionKey -> modifySessionSet(sessionKey, true));
//clear keys for sessions not in redis
log.info("UPDATE_USER_SESSION - {} - success", updateUserSessionMessage.getUuid().toString());
}
@Override
public void destroy()
{
}
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException
{
HttpSession session = httpServletRequest.getSession();
if (session != null)
{
String sessionId = session.getId();
if (permissionsToUpdate.contains(sessionId))
{
try
{
SecurityContextImpl securityContextImpl = (SecurityContextImpl) session.getAttribute("SPRING_SECURITY_CONTEXT");
if (securityContextImpl != null)
{
Authentication auth = securityContextImpl.getAuthentication();
Optional<User> user = auth != null
? userJPARepository.findByUsername(auth.getName())
: Optional.empty();
if (user.isPresent())
{
user.get().getAccessControls().forEach(ac -> ac.setUsers(null));
MyCustomUser myCustomUser = new MyCustomUser (user.get().getUsername(),
user.get().getPassword(),
user.get().getAccessControls(),
user.get().getOrganization().getId());
final Authentication newAuth = new UsernamePasswordAuthenticationToken(myCustomUser ,
null,
user.get().getAccessControls());
SecurityContextHolder.getContext().setAuthentication(newAuth);
session.setAttribute("SPRING_SECURITY_CONTEXT", newAuth);
}
else
{
//invalidate the session if the user could not be found
session.invalidate();
}
}
else
{
//invalidate the session if the user could not be found
session.invalidate();
}
}
finally
{
modifySessionSet(sessionId, false);
}
}
}
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
我试图使用Spring Cloud的Zuul、Eureka和我自己的服务实现微服务架构。我有多个具有UI和服务的服务,每个服务都可以使用x509安全性对用户进行身份验证。现在我想把祖尔放在那些服务机构的前面。由于Zuul无法将客户端证书转发到后端,我认为下一个最好的方法是在Zuul的前门对用户进行身份验证,然后使用Spring会话在后端服务中复制他们的身份验证状态。我遵循了Dave Syer的教程
我正在尝试将spring boot配置为使用mongoDB存储用户和会话。我可以将用户和会话存储在不同的项目中,但当我将它们存储在同一个项目中时,SessionRepositoryFilter的Autowired将失败。 这里的错误是: 谢谢;)
问题内容: 我是Redis的新手。我已经按照本教程将HttpSession与redis一起使用。 https://docs.spring.io/spring- session/docs/current/reference/html5/guides/boot.html 现在,我的应用程序具有“从所有设备注销”选项。单击后,如何删除或使该用户的所有会话无效? 另外,当用户更改密码时,如何使除当前会话之
据我所知,spring启动和spring会话为我们提供了一站式自动配置,但当我的应用程序使用会话redis和应用程序缓存redis时,它们不是同一个redis服务器;我如何配置它,非常感谢您的回复!
问题内容: 我正在维护Java Web应用程序。 通过登录代码,它可以通过HttpServletRequest的getSession()方法从HttpServletRequest中获取一个HttpSession。(它在会话中使用一些值进行认证) 但是,我担心会话固定攻击,因此在使用初始会话后,我想开始一个新会话或更改会话ID。这可能吗? 问题答案: Servlet 3.0 API不允许您更改现有会
问题内容: 我正在尝试将Redis会话集成到用Node.js编写的身份验证系统中。 我已经能够成功设置Redis服务器和Express服务器。 这是我的设置(只是重要的一点): 现在…我该如何实际创建,阅读和销毁会话?我已经阅读了很多关于如何设置的文章以及关于SO的许多问题,但是我发誓每个都只停留在配置上,并且不解释如何实际使用它… 我知道这可能非常简单,但是请不要投票,而只是解释一下:)。 问题