spring security oauth2的学习过程(二)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_18416057/article/details/86765492

     前面我们已经把基本的授权服务器弄好了,并能根据四种方式获取到token了。今天就再讲讲具体的一些东西。

今天要做的事情如下

1,管理用户数据

2,修改原生返回token的内容(令牌增强器)

3,tokenStore(令牌持久化接口,令牌存储介质)

    管理用户数据

        比方我们前一篇文中的用户名和密码是使用spring security auth2.0 默认产生的,那如果使用我们的一套用户体系怎么弄呢?我们这里先看一下增加几个账号怎么加?加的方式其实很简单,本身原来中就提供了内存式的userdetailService,数据库式的jdbcdetailservice

替换auth2.0中跟用户操作有关的类UserDetailsService,JdbcUserDetailService,InMemoryUserDetailsManager等相关类。大家有空可以去看一下这一块的代码,根据你的设置采用不同的userDetailService,相关的类还有如下

 然后有一个最重要的方法是loadUserByUserName方法,如果现有的一些UserDetailService还是无法满足你们系统的业务需求的,那你可以自己写一个类实现UserDetailService接口,重新loadUserByUserName就可以了,auth2.0内部会自动使用你这个类。

回到原点,我们先讲一下内存式加账号的方式。只需要在我们的AuthServerConfig类中加如下代码

@Bean
protected UserDetailsService userDetailsService(){
    InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
    manager.createUser(User.withUsername("user_1").password("123456").authorities("USER").build());
    manager.createUser(User.withUsername("user_2").password("123456").authorities("USER").build());
    return manager;
}

这样就可以了

数据库式的也只要在上面的代码改成如下

  @Bean
    protected UserDetailsService userDetailsService(){
        JdbcUserDetailsManager manager = new JdbcUserDetailsManager();
        return  manager;
    }

注意一下:这个数据库式的方式一定要满足它自己本身的数据库表设计,从源码中可以看出来

如果你自己要设计出符合自己系统的UserDetailService,就按照我上面的做法就可以了

2,讲下来我们怎么修改原生token的内容

这里我们只需要增加一个CustomTokenEnhancer实现TokenEnhancer重新enhance方法,这个方法就是修改原生token的方法

public class CustomTokenEnhancer implements TokenEnhancer {
    @Override
    public OAuth2AccessToken enhance(OAuth2AccessToken oAuth2AccessToken, OAuth2Authentication oAuth2Authentication) {
        DefaultOAuth2AccessToken token = null;
        if (oAuth2AccessToken instanceof DefaultOAuth2AccessToken) {
            token = ((DefaultOAuth2AccessToken) oAuth2AccessToken);
            //token.setValue(getNewToken());  //修改token的vakue值

            String type = oAuth2AccessToken.getTokenType();
            if ("authorization_code".equals(type)) {
                //如果授权方式是code的方式,在兼容原先的基础上更改,增加一个过期时间
                Map<String, Object> additionalInformation = new HashMap<String, Object>();
                additionalInformation.put("refresh_exp", token.getExpiration());
                token.setAdditionalInformation(additionalInformation);
            }
        }
        return token;
    }
}

然后在Oauth2ServerConfig中加如下代码


    @Bean
    public TokenEnhancer tokenEnhancer() {
        return new CustomTokenEnhancer();
       // return  new TokenEnhancerChain();
    }
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        //super.configure(endpoints);
        endpoints.authenticationManager(authenticationManager);

       // 将令牌增强器增加到增强器链中
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer()));
        endpoints.tokenEnhancer(tokenEnhancerChain);


    }

想弄清楚到底怎么弄的,大家自己也可以去看看源码,大概就是你自己自定义一个tokenEnhance,然后将自己定义的tokenEnhance放到tokenEnhanceChain(token增强链),然后设置到endpoint中,这样你就可以自主的修改原有的token内容

3,设置tokenStore

跟clientId,serect一样有多种方式,InMemoryTokenStore,JdbcTokenStore,JTWTokenStore等

auth2.0默认采用InMemoryTokenStore方式,直接将token放在内存中,在单服务中还是比较好的,简单便捷。

JdbcTokenStore是将token存储在数据库中,相比内存的单服务,数据库形式就可以保证多服务共享。auth2.0默认给了一套数据库的结构,然后使用JdbcTokenStore,内部一些功能也已经实现好了,你只要对接上去就好了

现在主要讲另一种JTWTokenStore,关于jwt大家可以读一下沅一峰的jwt文章,下面附上链接

http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html

读完上面的文章大概应该有所了解了

下面看具体实现,新增如下类,代码如下:

@Configuration
public class JwtTokenConfig {

    private final Logger logger = LoggerFactory.getLogger(JwtTokenConfig.class);


    public JwtTokenConfig() {logger.info("Loading JwtTokenConfig ...");}

    @Bean
    public TokenStore jwtTokenStore() {
        return new JwtTokenStore(jwtAccessTokenConverter());
    }

    // 用来生成jwt
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();

        //生成签名的key
        //秘签
        jwtAccessTokenConverter.setSigningKey("zfh");
        return jwtAccessTokenConverter;
    }
}

然后在auth2ServerConfig类加增加如下代码

public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        //super.configure(endpoints);
        endpoints.authenticationManager(authenticationManager);

        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer(),jwtAccessTokenConverter));
        endpoints.tokenEnhancer(tokenEnhancerChain);

        //设置tokenstore
   //     endpoints.tokenStore(jwtTokenStore)
    //            .accessTokenConverter(jwtAccessTokenConverter);


    }

其实我看了一下就是一个TokenEnhancer,所以就按照Enhancer加到endpoint里面就好了,再请求token之后结果如下

{
    "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJ1c2VyXzEiLCJzY29wZSI6WyJhcHAiXSwiZXhwIjoxNTQ5NTgwODI2LCJ6ZmgiOiIxMjM0IiwiYXV0aG9yaXRpZXMiOlsiVVNFUiJdLCJqdGkiOiI4ODI0MjNiYy1mYWNmLTRjOTEtYWY4MC0zNDQzNDJjYjI2ZDkiLCJjbGllbnRfaWQiOiJjbGllbnRJZCJ9.vUtzh_EQNkYwqhQYA4rvgp3BPJy3zdC9xFv9b8dz1PA",
    "token_type": "bearer",
    "expires_in": 43190,
    "scope": "app",
    "zfh": "1234",
    "jti": "882423bc-facf-4c91-af80-344342cb26d9"
}

这是经过两个token增强器所得到的结果,上面的jwt加密是对称加密,大家也可以使用非对称加密方式

猜你喜欢

转载自blog.csdn.net/qq_18416057/article/details/86765492