在Spring Security+中实现刷新令牌;有棱角的

在Spring Security+中实现刷新令牌;有棱角的,spring,spring-boot,spring-security,angular9,angular-oauth2-oidc,Spring,Spring Boot,Spring Security,Angular9,Angular Oauth2 Oidc,我正在与OAuth2和JWT一起研究春季安全性: 根据作者的说法,我可以通过以下方式使用令牌访问资源: 访问资源使用(您需要配置ResourceServer的其他应用程序): http本地主机:8080/用户授权:承载人“$ACCESS\u令牌” 关于此步骤: 使用刷新令牌功能: http——表单POST adminapp:password@localhost:9999/oauth/token grant\u type=refresh\u token refresh\u token=$refre

我正在与OAuth2和JWT一起研究春季安全性:

根据作者的说法,我可以通过以下方式使用令牌访问资源:

访问资源使用(您需要配置ResourceServer的其他应用程序):

http本地主机:8080/用户授权:承载人“$ACCESS\u令牌”

关于此步骤:

使用刷新令牌功能:

http——表单POST adminapp:password@localhost:9999/oauth/token grant\u type=refresh\u token refresh\u token=$refresh\u token

我不清楚何时需要刷新令牌,以及如何将此部分处理为Angular。 当令牌过期时,我是否需要首先向端点发送刷新令牌的请求,然后再向登录页面发送请求


如何实现这种情况?

在进行身份验证时,将创建两个JWT—访问令牌和刷新令牌。刷新令牌的有效期将延长。这两个令牌都将写入cookie中,以便在每次后续请求中发送它们

在每次RESTAPI调用中,将从HTTP头检索令牌。如果访问令牌未过期,请检查用户的权限并相应地允许访问。如果访问令牌已过期,但刷新令牌有效,请重新创建新的访问令牌,并使用新的过期日期刷新令牌,并通过cookie发送回


访问令牌携带直接访问资源所需的信息。换句话说,当客户端将访问令牌传递给管理资源的服务器时,该服务器可以使用令牌中包含的信息来决定客户端是否被授权。访问令牌通常有一个过期日期,并且是短期的

刷新令牌携带获取新访问令牌所需的信息。换句话说,每当需要访问令牌来访问特定资源时,客户端可以使用刷新令牌来获取由认证服务器颁发的新访问令牌。常见的用例包括在旧的访问令牌过期后获取新的访问令牌,或者第一次获取对新资源的访问。刷新令牌也可能过期,但寿命相当长


高级代码

public ResponseEntity<OAuth2AccessToken> authenticate(HttpServletRequest request, HttpServletResponse response, Map<String, String> params) {
        try {
            String username = params.get("username");
            String password = params.get("password");
            boolean rememberMe = Boolean.valueOf(params.get("rememberMe"));
            OAuth2AccessToken accessToken = authorizationClient.sendPasswordGrant(username, password);
            OAuth2Cookies cookies = new OAuth2Cookies();
            cookieHelper.createCookies(request, accessToken, rememberMe, cookies);
            cookies.addCookiesTo(response);
            if (log.isDebugEnabled()) {
                log.debug("successfully authenticated user {}", params.get("username"));
            }
            return ResponseEntity.ok(accessToken);
        } catch (HttpClientErrorException ex) {
            log.error("failed to get OAuth2 tokens from UAA", ex);
            throw new BadCredentialsException("Invalid credentials");
        }
    }
验证()


不要在端点中使用类似于
HttpServletRequest
的东西来获取“请求者用户名”,该用户名应包含在项目代码中,用于检查是否每个请求都验证了您的“安全要求”。此时,您应该在Spring主体用户中包含用户名、角色等,以便在代码的其他部分获得此类信息。您应该始终在请求中发送JWT,这样您就可以检查给定的JWT是否通过了项目中包含的安全功能。关于
刷新令牌
,您的登录操作至少应返回
访问
刷新令牌
。在每个请求中使用访问令牌,当您的安全功能返回“类似于”
时使用刷新令牌。您没有与安全相关的问题,但提供的访问令牌已过期(具有相应的Http代码)有什么好的代码示例可以给我看吗?这里有一个解释:@PeterPenzov,在角度方面,您可以使用拦截器从后端侦听令牌过期响应。获得令牌过期响应后,需要使用当前拥有的刷新令牌(在浏览器存储中)请求新令牌。如果刷新令牌有效(表示未过期),您将获得一组新的令牌(访问令牌和刷新令牌)。这样,您就可以重试失败的RESTAPI调用。若刷新令牌本身已过期,则重定向到登录页面。我认为这可能对您的集成有所帮助,我不确定,但我怀疑
HttpServletRequest
不会有用,因为我使用Angular frontend,然后向Spring发出Rest API请求。例如,是否有其他方法使用SpringBeans来配置此功能?您将从
HttpServletRequest
获取Cookie以及其他需要的详细信息。您可能需要使用sprint引导管理令牌,客户端将只负责发送cookie和所需的头。我使用sprint boot和angular实现了同样的功能,效果非常好。
public HttpServletRequest refreshToken(HttpServletRequest request, HttpServletResponse response, Cookie refreshCookie) {
        //check if non-remember-me session has expired
        if (cookieHelper.isSessionExpired(refreshCookie)) {
            log.info("session has expired due to inactivity");
            logout(request, response); //logout to clear cookies in browser
            return stripTokens(request); //don't include cookies downstream
        }
        OAuth2Cookies cookies = getCachedCookies(refreshCookie.getValue());
        synchronized (cookies) {
            //check if we have a result from another thread already
            if (cookies.getAccessTokenCookie() == null) { //no, we are first!
                //send a refresh_token grant to UAA, getting new tokens
                String refreshCookieValue = OAuth2CookieHelper.getRefreshTokenValue(refreshCookie);
                OAuth2AccessToken accessToken = authorizationClient.sendRefreshGrant(refreshCookieValue);
                boolean rememberMe = OAuth2CookieHelper.isRememberMe(refreshCookie);
                cookieHelper.createCookies(request, accessToken, rememberMe, cookies);
                //add cookies to response to update browser
                cookies.addCookiesTo(response);
            } else {
                log.debug("reusing cached refresh_token grant");
            }
            //replace cookies in original request with new ones
            CookieCollection requestCookies = new CookieCollection(request.getCookies());
            requestCookies.add(cookies.getAccessTokenCookie());
            requestCookies.add(cookies.getRefreshTokenCookie());
            return new CookiesHttpServletRequestWrapper(request, requestCookies.toArray());
        }
    }