• springboot和springsecurity使用JWT令牌


    基于之前的文章springboot和springsecurity整合OAuth2

    略有修改

    1. 授权模块修改OauthServerConfig配置文件

    @Configuration
    @EnableAuthorizationServer
    public class OauthServerConfig extends AuthorizationServerConfigurerAdapter {
        @Autowired
        private DataSource dataSource;
        @Autowired
        private UserDetailsService userDetailsService;
        @Autowired
        private AuthenticationManager authenticationManager;
        @Autowired
        private PasswordEncoder passwordEncoder;
    
        private String SIGNING_KEY = "salt";
    
    
        //从数据库中查询出客户端信息
        @Bean
        public JdbcClientDetailsService clientDetailsService() {
            JdbcClientDetailsService jdbcClientDetailsService = new JdbcClientDetailsService(dataSource);
            jdbcClientDetailsService.setPasswordEncoder(passwordEncoder);
            return jdbcClientDetailsService;
        }
    
        @Bean
        public TokenStore tokenStore() {
            return new JwtTokenStore(accessTokenConverter());
        }
    
        @Bean
        public JwtAccessTokenConverter accessTokenConverter() {
            JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
            converter.setSigningKey(SIGNING_KEY);  //对称秘钥,资源服务器使用该秘钥来验证
            return converter;
        }
    
        //授权信息保存策略
        @Bean
        public ApprovalStore approvalStore() {
            return new JdbcApprovalStore(dataSource);
        }
    
        //授权码模式专用对象
        @Bean
        public AuthorizationCodeServices authorizationCodeServices() {
            return new JdbcAuthorizationCodeServices(dataSource);
        }
    
        //指定客户端登录信息来源
        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            //从数据库取数据
            clients.withClientDetails(clientDetailsService());
        }
    
        //检测token的策略
        @Override
        public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
            oauthServer.allowFormAuthenticationForClients()    //允许form表单客户端认证,允许客户端使用client_id和client_secret获取token
                    .checkTokenAccess("permitAll()")     //对校验token接口设置权限控制
                    .tokenKeyAccess("permitAll()")            // 获取token请求不进行拦截
                    .passwordEncoder(passwordEncoder);
        }
    
        //OAuth2的主配置信息
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints
                    .approvalStore(approvalStore())
                    .authenticationManager(authenticationManager)
                    .authorizationCodeServices(authorizationCodeServices())
                    .tokenStore(tokenStore())
                    .userDetailsService(userDetailsService)
                    .tokenServices(tokenService())
                    .allowedTokenEndpointRequestMethods(HttpMethod.POST);
        }
    
        @Bean
        public AuthorizationServerTokenServices tokenService() {
            DefaultTokenServices tokenServices = new DefaultTokenServices();
            tokenServices.setClientDetailsService(clientDetailsService());
            tokenServices.setSupportRefreshToken(true);
            tokenServices.setTokenStore(tokenStore());
            tokenServices.setAccessTokenValiditySeconds(10800); // 令牌默认有效期2小时
            tokenServices.setRefreshTokenValiditySeconds(86400); // 刷新令牌默认有效期3天
            //新增对jwt配置
            TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
            tokenEnhancerChain.setTokenEnhancers(Arrays.asList(accessTokenConverter()));
            tokenServices.setTokenEnhancer(tokenEnhancerChain);
            return tokenServices;
        }
    }
    

    2. 修改资源模块OauthResourceConfig配置文件

    @Configuration
    @EnableResourceServer
    public class OauthResourceConfig extends ResourceServerConfigurerAdapter {
        @Autowired
        private DataSource dataSource;
        @Autowired
        private TokenStore tokenStore;
    
        private String SIGNING_KEY = "salt";
    
        /**
         * 指定token的持久化策略
         * 其下有   RedisTokenStore保存到redis中,
         * JdbcTokenStore保存到数据库中,
         * InMemoryTokenStore保存到内存中等实现类,
         * 这里我们选择保存在数据库中
         *
         * @return
         */
        @Bean
        public TokenStore tokenStore() {
            return new JwtTokenStore(accessTokenConverter());
        }
    
        @Bean
        public JwtAccessTokenConverter accessTokenConverter() {
            JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
            converter.setSigningKey(SIGNING_KEY);  //对称秘钥,资源服务器使用该秘钥来验证
            return converter;
        }
    
        public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
            resources.resourceId("product_api")//指定当前资源的id,非常重要!必须写!
                    .tokenStore(tokenStore) //指定保存token的方式
                    .stateless(true);
        }
    
        public void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                    //指定不同请求方式访问资源所需要的权限,一般查询是read,其余是write。
                    .antMatchers(HttpMethod.GET, "/**").access("#oauth2.hasScope('read')")
                    .antMatchers(HttpMethod.POST, "/**").access("#oauth2.hasScope('write')")
                    .antMatchers(HttpMethod.PATCH, "/**").access("#oauth2.hasScope('write')")
                    .antMatchers(HttpMethod.PUT, "/**").access("#oauth2.hasScope('write')")
                    .antMatchers(HttpMethod.DELETE, "/**").access("#oauth2.hasScope('write')")
                    .and()
                    .headers().addHeaderWriter((request, response) -> {
                response.addHeader("Access-Control-Allow-Origin", "*");//允许跨域
                if (request.getMethod().equals("OPTIONS")) {//如果是跨域的预检请求,则原封不动向下传达请求头信息
                    response.setHeader("Access-Control-Allow-Methods", request.getHeader("Access-Control-Request-Method"));
                    response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));
                }
            });
        }
    
        //资源服务令牌解析服务
    //    @Bean
    //    public ResourceServerTokenServices tokenService() {
    //        //使用远程服务请求授权服务器校验token,必须指定校验token  的url、client_id,client_secret
    //        RemoteTokenServices service = new RemoteTokenServices();
    //        service.setCheckTokenEndpointUrl("http://localhost:9001/oauth/check_token");
    //        service.setClientId("baidu");
    //        service.setClientSecret("12345");
    //        return service;
    //    }
    }
    
    

    主要讲原先的数据库认证改为jwt认证

    3. 测试

    1. 生成令牌

    2. 校验令牌

    3. 测试资源访问

    4. 示例代码

    码云

  • 相关阅读:
    minio临时凭证 下载大文件合并UInt8Arrays
    elupload 传参
    [k8s] 创建sa类型的kubeconfig
    JAVA字符流写数据的五种方式 145
    JAVA copy多级目录文件
    JAVA线程实现的第二种方式
    JAVA 序列化类168
    JAVA 字符流复制JAVA文件 147
    JAVA UDP发送案例
    JAVA中多线程的数据安全问题
  • 原文地址:https://www.cnblogs.com/ifme/p/12192562.html
Copyright © 2020-2023  润新知