当用户首次使用JWT,OAUTH2,Spring Security请求时,如何在服务层上获得JWT令牌字符串



我是JWT开发微服务的新手。这是我的项目结构:

第一个微服务用于对JWT和OAUTH2的用户进行身份验证 使用用户名和密码。此微服务称为auth-Service。

登录请求URL就像:

[http://localhost:9092/oauth/token?username = s@sawai.com& password = randompassword& grant_type = password] [1]

通过调用此URL,我们得到了JWT令牌,例如:

{"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsib2F1dGgyX2lkIl0sInVzZXJfbmFtZSI6InNAc2F3YWkuY29tIiwic2NvcGUiOlsicmVhZCIsIndyaXRlIl0sInRlbmFudElkIjoic2F3YWkuY29tIiwic3lzdGVtR2VuZXJhdGVkUGFzc3dvcmQiOnRydWUsImlkIjoiNTYzOTFhYzAtZDc4OC00ODEyLThmYWMtODEwZTIyMjdjYmI1IiwiZXhwIjoxNTI0NzMxNzgwLCJhdXRob3JpdGllcyI6WyJST0xFX0FETUlOIl0sImp0aSI6ImY0ZTNmNTM5LWRkNDgtNGMxMy05OTg5LTcwM2E1NWYxMjNlYyIsImVtYWlsIjoic0BzYXdhaS5jb20iLCJjbGllbnRfaWQiOiJ0cnVzdGVkLWFwcCJ9.AS1tXpUcPMgEw63FrvPP-xGBz7qCi14Eqe29rDzTXPg","token_type":"bearer","refresh_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsib2F1dGgyX2lkIl0sInVzZXJfbmFtZSI6InNAc2F3YWkuY29tIiwic2NvcGUiOlsicmVhZCIsIndyaXRlIl0sImF0aSI6ImY0ZTNmNTM5LWRkNDgtNGMxMy05OTg5LTcwM2E1NWYxMjNlYyIsInRlbmFudElkIjoic2F3YWkuY29tIiwic3lzdGVtR2VuZXJhdGVkUGFzc3dvcmQiOnRydWUsImlkIjoiNTYzOTFhYzAtZDc4OC00ODEyLThmYWMtODEwZTIyMjdjYmI1IiwiZXhwIjoxNTI0NzQ2MTgwLCJhdXRob3JpdGllcyI6WyJST0xFX0FETUlOIl0sImp0aSI6IjI1ZmJlY2IyLWRhODgtNDY1ZS1iM2I2LTFlN2NmYjBlYmVjMiIsImVtYWlsIjoic0BzYXdhaS5jb20iLCJjbGllbnRfaWQiOiJ0cnVzdGVkLWFwcCJ9.jSG5zUBzu9yGqnBueU7fkIZV6XhXD8oCkYCerwHkkOw","expires_in":14399,"scope":"read write","tenantId":"sawai.com","systemGeneratedPassword":true,"id":"56391ac0-d788-4812-8fac-810e2227cbb5","email":"s@sawai.com","jti":"f4e3f539-dd48-4c13-9989-703a55f123ec"}

在身份服务数据库上,我们只创建一个名为用户的单个表格,其中包括以下字段:

id varchar(255(

Create_on DateTime

last_modified_date dateTime

电子邮件varchar(255(

启用位(1(

密码varchar(255(

角色varchar(255(

system_ganerated_password位(1(

tenant_id varchar(255(

验证位(1(

好的。

现在,另一个微服务称为公司,在公司服务中,我们有用户列表(与身份服务的用户不同,因为Auth Service包含了多个微服务的用户,例如:公司,候选人,等(。

现在,我们要为公司用户维护 last_logged_on 。因此,管理员可以检查上一次用户何时登录。

我们尝试做的是:当使用身份服务和用户类型的用户登录时,用户是用户,然后调用公司服务并更新用户 last_logged_on 。为了致电公司服务,我们需要JWT-Access-token,因为URL在公司方面是安全的。因此

这是JWT的配置

package com.cs.je.auth.config.jwt;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultUserAuthenticationConverter;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import com.cs.je.auth.enums.Role;
import com.cs.je.auth.model.User;
/**
 * @author sawai
 *
 */
@Configuration
@EnableAuthorizationServer
public class AuthorizationConfig extends AuthorizationServerConfigurerAdapter {
    @Value("${auth.token.time}")
    private int accessTokenValiditySeconds;
    @Value("${refresh.token.time}")
    private int refreshTokenValiditySeconds;
    @Value("${security.oauth2.resource.id}")
    private String resourceId;
    @Value("${trusted.app.name}")
    private String trustedAppName;
    @Value("${trusted.app.secret}")
    private String trustedAppSecret;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private CustomAccessTokenConverter customAccessTokenConverter;
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
                .authenticationManager(this.authenticationManager)
                .tokenServices(tokenServices())
                .tokenStore(tokenStore())
                .accessTokenConverter(accessTokenConverter());
    }
    @Bean
    public TokenEnhancer tokenEnhancer() {
        return new CustomTokenEnhancer();
    }
    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer
        // we're allowing access to the token only for clients with 'ROLE_TRUSTED_CLIENT' authority
                //.tokenKeyAccess("permitAll()")
                .tokenKeyAccess("hasAuthority('ROLE_TRUSTED_CLIENT')")
                .checkTokenAccess("hasAuthority('ROLE_TRUSTED_CLIENT')");
    }
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient(trustedAppName)
                    .authorizedGrantTypes("client_credentials", "password", "refresh_token")
                    .authorities("ROLE_TRUSTED_CLIENT")
                    .scopes("read", "write")
                    .resourceIds(resourceId)
    //                .accessTokenValiditySeconds(accessTokenValiditySeconds)
    //               .refreshTokenValiditySeconds(refreshTokenValiditySeconds)
                    .secret(trustedAppSecret);
    }
    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(accessTokenConverter());
    }
    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        System.out.println("3333333333333");
        DefaultAccessTokenConverter tokenConverter = new DefaultAccessTokenConverter();
        tokenConverter.setUserTokenConverter(new DefaultUserAuthenticationConverter() {
            @Override
            public Authentication extractAuthentication(Map<String, ?> map) {
                Authentication authentication = super.extractAuthentication(map);
                System.out.println("222222222222");
                // User is my custom UserDetails class
                User user = new User();
                user.setTenantId(map.get("tenantId").toString());
                user.setEmail(map.get("email").toString());
                user.setId(map.get("id").toString());
                //user.setPassword(map.get("password").toString());
                //System.out.println("date " + );
                Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
                authorities.addAll(authentication.getAuthorities());
                user.setGrantedAuthorities(authorities);
                user.setRole(Role.valueOf(authorities.iterator().next().toString()));
                //user.setSpecialKey(map.get("specialKey").toString());
                return new UsernamePasswordAuthenticationToken(user,
                        authentication.getCredentials(), authentication.getAuthorities());
            }
        });
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey("key");
        converter.setAccessTokenConverter(customAccessTokenConverter);
        converter.setAccessTokenConverter(tokenConverter);
        return converter;
    }    
    @Bean
    @Primary
    public DefaultTokenServices tokenServices() {
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer(), accessTokenConverter()));
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(tokenStore());
        defaultTokenServices.setSupportRefreshToken(true);
        defaultTokenServices.setAccessTokenValiditySeconds(accessTokenValiditySeconds);
        defaultTokenServices.setRefreshTokenValiditySeconds(refreshTokenValiditySeconds);
        defaultTokenServices.setReuseRefreshToken(false);
        defaultTokenServices.setTokenEnhancer(tokenEnhancerChain);
        return defaultTokenServices;
    }    
}

这是自定义令牌增强:

package com.cs.je.auth.config.jwt;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.stereotype.Component;
import com.cs.je.auth.enums.Role;
import com.cs.je.auth.model.User;
import com.cs.je.auth.rest.api.call.CustomRestTemplate;
import com.cs.je.auth.service.UserService;
import com.cs.je.auth.utils.EncTokenUtils;
import com.cs.je.auth.utils.UserUtils;
/**
 * @author sawai
 *
 */
@Component
public class CustomTokenEnhancer implements TokenEnhancer {
    @Autowired
    private UserService userService;
    @Autowired
    private CustomRestTemplate customRestTemplate;
    @Value("${microservice.company.protocol}")
    private String protocol;
    @Value("${microservice.company.port}")
    private String port;
    @Value("${microservice.company.ip}")
    private String ipAddress;
    @Value("${microservice.company.user.api}")
    private String userCreateUrl;
    @Autowired
    private TokenStore tokenStore;
    @Override
    public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
        Map<String, Object> additionalInfo = new HashMap<>();
        if (authentication != null) {
            User user = (User)authentication.getPrincipal();
            additionalInfo.put("email", user.getEmail());
            additionalInfo.put("tenantId", user.getTenantId());
            additionalInfo.put("id", user.getId());
            if (user.isSystemGeneratedPassword()) {
                additionalInfo.put("systemGeneratedPassword", true);
            }
            ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
            System.out.println(accessToken.getRefreshToken());
            System.out.println(accessToken.getRefreshToken().getValue());
            System.out.println(accessToken.getTokenType());

            /*if (user.getRole().equals(Role.ROLE_ADMIN) || user.getRole().equals(Role.ROLE_USER)) {
                 String token = accessToken.toString();
                 try {
                    System.out.println("before call");
                    //ResponseEntity<Object> responseEntity = customRestTemplate.exchange(protocol + "://" + ipAddress + ":" + port + userCreateUrl + "/" + user.getId() + "/last-loggedOn", token, EncTokenUtils.getEncToken(user.getEmail()), HttpMethod.PUT, null);
                    System.out.println("successfull");
                 } catch (Exception e) {
                    e.printStackTrace();
                } 
            }*/
            System.out.println("1111111111");
        }
        return accessToken;
    }
}

安全配置

package com.cs.je.auth.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import com.cs.je.auth.constant.Constants;
import com.cs.je.auth.enums.Role;
import com.cs.je.auth.model.User;
import com.cs.je.auth.repository.UserRepository;
import com.cs.je.auth.service.UserService;
/**
 * @author sawai
 *
 */
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserService userService;
    @Autowired
    private UserRepository userRepository;
    /*@Override
    public void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.authorizeRequests().antMatchers(HttpMethod.OPTIONS).permitAll()
        .antMatchers("/").permitAll()
        .antMatchers(HttpMethod.POST ,"/user/**").hasAnyAuthority("ROLE_SUPER_USER", "ROLE_ADMIN")
        .anyRequest().authenticated();
        httpSecurity.csrf().disable();
        httpSecurity.headers().frameOptions().disable();
        httpSecurity.requestCache().requestCache(new NullRequestCache());
        httpSecurity.httpBasic();
        //httpSecurity.addFilterBefore(CORSFilter, ChannelProcessingFilter.class);
    }*/
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder);
        if (userRepository.count() < 1) {
            User user = new User();
            user.setEmail("jeAdmin@email.com");
            user.setPassword("jeAdminUser");
            user.setTenantId(Constants.JE_TENANT_ID);
            user.setRole(Role.ROLE_SUPER_USER);
            user.setValidate(true);
            userService.create(user, null);
        }
     }
    @Override
    public void configure(WebSecurity webSecurity) {
        webSecurity.ignoring().antMatchers("/api/candidate/**");
        webSecurity.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
        webSecurity.ignoring().antMatchers("/api/company/**");
        webSecurity.ignoring().antMatchers("/api/forgotPassword/**");
        //webSecurity.ignoring().antMatchers(HttpMethod.POST, "/oauth/**");
    }
}

resourceconfig.java

package com.cs.je.auth.config.jwt;
/**
 * @author sawai
 *
 */
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.web.access.channel.ChannelProcessingFilter;
import org.springframework.security.web.savedrequest.NullRequestCache;
import com.cs.je.auth.filter.CORSFilter;
@Configuration 
@EnableResourceServer
public class ResourceConfig extends ResourceServerConfigurerAdapter {
    @Value("${security.oauth2.resource.id}")
    private String resourceId;
    // The DefaultTokenServices bean provided at the AuthorizationConfig
    @Autowired
    private DefaultTokenServices tokenServices;
    // The TokenStore bean provided at the AuthorizationConfig
    @Autowired
    private TokenStore tokenStore;
    @Autowired
    private CORSFilter corsFilter;
    // To allow the rResourceServerConfigurerAdapter to understand the token,
    // it must share the same characteristics with AuthorizationServerConfigurerAdapter.
    // So, we must wire it up the beans in the ResourceServerSecurityConfigurer.
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources
                .resourceId(resourceId)
                .tokenServices(tokenServices)
                .tokenStore(tokenStore);
    }

    public void configure(WebSecurity webSecurity) {
        webSecurity.ignoring().antMatchers("/api/candidate/**");
    //  webSecurity.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
    //  webSecurity.ignoring().antMatchers(HttpMethod.POST, "/oauth/**");
    }
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
        .authorizeRequests().antMatchers("/").permitAll().and().authorizeRequests().antMatchers("/console/**")
        .permitAll().and().authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll().and()
                // when restricting access to 'Roles' you must remove the "ROLE_" part role
                // for "ROLE_USER" use only "USER"
                //.antMatchers("/api/hello").access("hasAnyRole('USER')")          
                //.antMatchers("/api/admin").hasRole("ADMIN")
                .authorizeRequests().antMatchers(HttpMethod.POST ,"/api/user/**").hasAnyAuthority("ROLE_SUPER_USER", "ROLE_ADMIN")
                // restricting all access to /api/** to authenticated users
                //.antMatchers("/**")
                //.antMatchers("/api/**").authenticated();
                .anyRequest().authenticated();
        http.csrf().disable();
        http.headers().frameOptions().disable();
        http.requestCache().requestCache(new NullRequestCache());
        http.httpBasic();
        http.addFilterBefore(corsFilter, ChannelProcessingFilter.class);
    }
}

上面的所有配置都位于身份服务方面。现在,当用户对AUTH上的JWT令牌请求时,我们希望在服务层上获得访问toke值,因此我可以通过Secure URL调用来调用Company Service。

当用户请求JWT令牌时,请指导我如何获得访问token值。如果您在CustomTokenEnhancer中查看,那么我们尝试通过使用以下语句来打印在此处的访问:

**System.out.println(accessToken.getRefreshToken());
System.out.println(accessToken.getRefreshToken().getValue());
System.out.println(accessToken.getTokenType());**

但值类似于: 642E0CF2-9214-42D8-AE85-29E5CDFCCEF1 但是我们希望在这里进行实际令牌。

请指导我。

您可以使用该方法

public static final String AUTHORIZATION_HEADER = "Authorization";
public static final String TOKEN_SEPERATOR = " ";
public static String getAccessToken(){
    RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
    if (requestAttributes instanceof ServletRequestAttributes) {
        HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();
        return Arrays.asList(request.getHeader(AUTHORIZATION_HEADER).split(TOKEN_SEPERATOR)).get(1);
    }
    return null;
}

相关内容

最新更新