首页 文章

使用带有OAuth2和JHipster的Basic auth

提问于
浏览
0

我们使用jhipster通过OAuth2身份验证生成网关和微服务,并且可以与JHipster Registry和Keycloak服务器一起使用 . 但我们有一个将从外部服务调用的微服务,该服务使用基本身份验证 .

因此,在网关上,我们需要从基本身份验证服务器向keycloak服务器发送登录和密码,并使用访问令牌来调用我们的服务 . 我通过在MicroserviceSecurityConfiguration类中添加过滤器来获取访问令牌:

http.addFilterBefore(basicAuthFilter, UsernamePasswordAuthenticationFilter.class);

这里有一个过滤方法的摘录:

ResourceOwnerPasswordResourceDetails details = new ResourceOwnerPasswordResourceDetails();
details.setAccessTokenUri("http://keycloakserver/auth/realms/jhipster/protocol/openid-connect/token");
details.setGrantType("password");
details.setClientId("clientId");
details.setClientAuthenticationScheme(AuthenticationScheme.form);
details.setUsername(login);
details.setPassword(password);

AccessTokenRequest tokenRequest = new DefaultAccessTokenRequest();
ResourceOwnerPasswordAccessTokenProvider provider = new ResourceOwnerPasswordAccessTokenProvider();

OAuth2AccessToken accessToken = provider.obtainAccessToken(details, tokenRequest);

我想我必须在tokenStore中存储这个令牌,但我不知道如何 . 所以我的问题是如何使用这个令牌,我得到它的方式是否正确?

谢谢你的帮助 !

2 回答

  • 0

    我在 生产环境 系统中遇到同样的问题,然后我将认证服务器更改为JHipster UAA服务器,问题得到解决 .

    我想你现在正在使用第一种:

    OAuth 2.0 / OIDC身份验证:它使用OpenID Connect服务器,如Keycloak或Okta,它处理应用程序之外的身份验证 .

    使用JHipster UAA服务器进行身份验证:这使用必须单独生成的JHipster UAA服务器,以及处理应用程序外部身份验证的OAuth2服务器 .

  • 0

    经过一些测试和反复试验,我设法做到了我想要的 .

    首先,我创建了一个BasicAuthenticationFilter类:

    @Configuration
    public class BasicAuthenticationFilter implements Filter {
    
        private static final String GRANT_TYPE = "password";
        private static final String BASIC_AUTH_HEADER = "Authorization";
        private static final String BASIC_PREFIX = "Basic ";
    
        @Value("${security.oauth2.client.access-token-uri}")
        private String accessTokenUri;
    
        @Value("${security.oauth2.client.client-id}")
        private String clientId;
    
        @Value("${security.oauth2.client.client-secret}")
        private String clientSecret;
    
        @Autowired
        private TokenStore tokenStore;
    
        private ResourceOwnerPasswordAccessTokenProvider provider;
    
        public BasicAuthenticationFilter( ) {
            provider = new ResourceOwnerPasswordAccessTokenProvider();
        }
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    
            String header = null;
            if (request instanceof HttpServletRequest) {
                HttpServletRequest httpRequest = (HttpServletRequest) request;
                header = httpRequest.getHeader(BASIC_AUTH_HEADER);
                if (header != null && header.startsWith(BASIC_PREFIX)) {
                    String base64 = header.substring(BASIC_PREFIX.length());
                    String loginPassword = new String(Base64.getDecoder().decode(base64.getBytes()));
                    String[] split = loginPassword.split(":");
                    String login = split[0];
                    String password = split[1];
                    authenticate(httpRequest, login, password);
                }
            }
            chain.doFilter(request, response);
        }
    
        private void authenticate(HttpServletRequest httpRequest, String login, String password) {
            ResourceOwnerPasswordResourceDetails details = new ResourceOwnerPasswordResourceDetails();
            details.setAccessTokenUri(accessTokenUri);
            details.setGrantType(GRANT_TYPE);
            details.setClientId(clientId);
            details.setClientAuthenticationScheme(AuthenticationScheme.query);
            details.setUsername(login);
            details.setPassword(password);
    
            DefaultAccessTokenRequest tokenRequest = new DefaultAccessTokenRequest();
            tokenRequest.setCurrentUri(httpRequest.getRequestURI());
            try {
                OAuth2AccessToken accessToken = provider.obtainAccessToken(details, tokenRequest);
                OAuth2Authentication oauth2Authentication = tokenStore.readAuthentication(accessToken);
                AccessTokenDetails accessTokenDetail = new AccessTokenDetails(accessToken.getValue());
                oauth2Authentication.setDetails(accessTokenDetail);
                SecurityContext context = SecurityContextHolder.getContext();
                context.setAuthentication(oauth2Authentication);
            } catch (OAuth2AccessDeniedException e) {
                throw new AccessDeniedException("Wrong credentials !");
            }
        }
    
        @Override
        public void destroy() {
        }
    
        public static class AccessTokenDetails {
    
            private static final String DEFAULT_TOKEN_TYPE = "bearer";
    
            public final String tokenType;
            public final String tokenValue;
    
            public AccessTokenDetails(String tokenValue) {
                this(DEFAULT_TOKEN_TYPE, tokenValue);
            }
    
            public AccessTokenDetails(String tokenType, String tokenValue) {
                this.tokenType = tokenType;
                this.tokenValue = tokenValue;
            }
        }
    
    }
    

    此筛选器检查是否存在基本身份验证,如果是,则验证用户身份 . 身份验证详细信息存储在内部类AccessTokenDetails中 . 因此,可以在AuthorizationHeaderUtil中读取令牌:

    public class AuthorizationHeaderUtil {
    
    
        public static String getAuthorizationHeader() {
            SecurityContext context = SecurityContextHolder.getContext();
            Authentication authentication = context.getAuthentication();
            Object details = authentication.getDetails();
            String tokenType = "";
            String tokenValue = "";
            if (details instanceof OAuth2AuthenticationDetails) {
                OAuth2AuthenticationDetails oauth2Details = (OAuth2AuthenticationDetails) details;
                tokenType = oauth2Details.getTokenType();
                tokenValue = oauth2Details.getTokenValue();
            } else if (details instanceof AccessTokenDetails) {
                AccessTokenDetails accessTokenDetails = (AccessTokenDetails) details;
                tokenType = accessTokenDetails.tokenType;
                tokenValue = accessTokenDetails.tokenValue;
            }
            return String.format("%s %s", tokenType, tokenValue);
        }
    }
    

    这个类是由JHipster生成的,我添加了对我使用的两个身份验证详细信息类的检查 .

    我希望这会有用 .

    丹尼斯

相关问题