Location>code7788 >text

Microservices Integration with springsecurity for Authentication

Popularity:999 ℃/2024-07-28 12:46:39

module:auth

1.Adding Dependencies:spring-cloud-starter-securitytogether withspring-cloud-starter-oauth2

2. Configure WebSecurityConfig: inject AuthenticationManager override configure

3. Configure tokenConfig

4. Authorized servicesAuthorizationServer extends AuthorizationServerConfigurerAdapter to configure the client detail tasks, token endpoint configuration

5. Implement UserDetailsService, override loadUserByUsername (the most familiar episode)

tips: here return the UserDetails object do not have to create their own, springsecurity provides a User class implements the UserDetails, through the builder pattern can be generated directly username, password, authorities and other information. If you need to distribute multiple parameters to other modules, it is recommended that you use json to convert the object from the database into a string to store the username, and then you can directly rewrite the username into a specific class.

module:gateway

First of all, clarify the role of the gateway: route forwarding, authentication, whitelisting release: for the current gateway route forwarding, if it is a whitelist will be directly released, if it is required to JWT verification needs to verify the legitimacy of the JWT

Authentication and authorization are provided in security, here we have authentication at the gateway, which means that the authorization module is performed in the individual microservices

gateway integrates with springsecurity:

1.Adding Dependencies:spring-cloud-starter-securitytogether withspring-cloud-starter-oauth2

2. Add configuration: filter; then add tokenConfig, securityConfig


/**
*
* @description Gateway Authentication Filter: This code is mainly used as a filter to deal with an http request, the first is to check whether the request path is in the whitelist, whether the request carries a token/has no expiration date and other security-related checks
*/

@Component @Slf4j
public class GatewayAuthFilter implements GlobalFilter, Ordered { //whitelisting private static List<String> whitelist = null; static { //Load Whitelist try ( InputStream resourceAsStream = GatewayAuthFilter.class.getResourceAsStream("/"); ) { Properties properties = new Properties(); (resourceAsStream); Set<String> strings = (); whitelist= new ArrayList<>(strings); } catch (Exception e) { ("(of cargo etc) load/make a mistake:{}",()); (); } } @Autowired private TokenStore tokenStore; @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { String requestUrl = ().getPath().value(); AntPathMatcher pathMatcher = new AntPathMatcher(); //white-listing for (String url : whitelist) { if ((url, requestUrl)) { return (exchange); } } //Check if the token exists String token = getToken(exchange); if ((token)) { return buildReturnMono("Not certified.",exchange); } //Determine if it is a valid token OAuth2AccessToken oAuth2AccessToken; try { oAuth2AccessToken = (token); boolean expired = (); if (expired) { return buildReturnMono("Authentication token has expired.",exchange); } return (exchange); } catch (InvalidTokenException e) { ("Invalid authentication token: {}", token); return buildReturnMono("Authentication token invalid.",exchange); } } /** * :: Obtaining a token */ private String getToken(ServerWebExchange exchange) { String tokenStr = ().getHeaders().getFirst("Authorization"); if ((tokenStr)) { return null; } String token = (" ")[1]; if ((token)) { return null; } return token; } private Mono<Void> buildReturnMono(String error, ServerWebExchange exchange) { ServerHttpResponse response = (); String jsonString = (new RestErrorResponse(error)); byte[] bits = (StandardCharsets.UTF_8); DataBuffer buffer = ().wrap(bits); (); ().add("Content-Type", "application/json;charset=UTF-8"); return ((buffer)); } @Override public int getOrder() { return 0; } }

    // Assuming the token has been obtained from the request
    String token = getToken(exchange);  
  
    // If the token exists and is not null
    if (token != null && !()) {  
        // Create a new ServerHttpRequest and add token to Authorization header
        ServerHttpRequest mutatedRequest = ().mutate()  
                .header("Authorization", "Bearer " + token)
                .build();  
  
        // Use the ServerWebExchangeDecorator to wrap the original ServerWebExchange, and use the modified request
        ServerWebExchange mutatedExchange = ()  
                .request(mutatedRequest)  
                .build();  

        return (mutatedExchange);  
    }  

3. Configure whitelist

/media/open/**=Media management open access interface

4. Release all routes in other microservice modules and get the object directly through ().getAuthentication() (because it has been verified in the gateway, here is only responsible for authorization)

module:others

1. Package a SecurityUtil.SecurityContextHolder.getContext().getAuthentication().getPrincipal(); you can get the specific username, and then username to entity classes can be used

@Slf4j
public class SecurityUtil {

    public static XcUser getUser() {
        try {
            Object principalObj = ().getAuthentication().getPrincipal();
            if (principalObj instanceof String) {
                //retrieve user identification information
                String principal = ();
                //Convert json to object
                XcUser user = (principal, XcUser.class);
                return user;
            }
        } catch (Exception e) {
            ("Error getting identity of currently logged in user:{}", ());
            ();
        }

        return null;
    }


    @Data
    public static class XcUser implements Serializable {

        private static final long serialVersionUID = 1L;

        private String id;

        private String username;

        private String password;

        private String salt;

        private String name;
        private String nickname;
        private String wxUnionid;
        private String companyId;
        /**
         * :: Avatars
*/
        private String userpic;

        private String utype;

        private LocalDateTime birthday;

        private String sex;

        private String email;

        private String cellphone;

        private String qq;

        /**
         * :: User status
*/
        private String status;

        private LocalDateTime createTime;

        private LocalDateTime updateTime;


    }


}

Usage Note: The above uses a member of the internal class, XcUser is defined in the member position of the external class, it can not create a separate object, you must rely on the external class instance.new internal class () to create the instance

 user = ();

 

Q&A:

token passed down in gateway?

(No oauth2 integration) Normally we need to modify ServerHttpRequest in ServerWebExchange, but ServerHttpRequest is immutable. So if we need to add a token, we need to create a new ServerWebExchange and rewrite the ServerHttpRequest.

In addition to this, since we will also pass the request to the next GatewayFilterChain, we can pass this request by modifying the ServerWebExchange's MutableHttpRequest when it is passed:

(with oauth2 integration) springsecurity's filter chain automatically handles extracting the token from the request and appending it to the context, and downstream filters get it through springsecurity's API.

 

Why can other microservice modules get objects directly via ().getAuthentication()?

In microservices, each module has its own JVM with its own thread, which means that theThe SecurityContext is different for each module.. When we use oauth2, the user authenticates through the above gateway and gets a jwt to put it in the request.

When a module receives an http request containing an oauth2 token, it uses this token to authenticate the user, and theBuilding a new SecurityContext based on a tokenThis means that the SecurityContext implementation is actually limited to a single thread of a single service. This means that the SecurityContext implementation is actually limited to a single thread for a single service, and cross-service security messaging is performed by oauth2