代码之家  ›  专栏  ›  技术社区  ›  parsecer

OAuth2Config:IllegalStateException:对于MAC签名,不需要单独指定验证器密钥

  •  0
  • parsecer  · 技术社区  · 6 年前

    我正在尝试创建一个使用Spring Security和JWT令牌的项目。然而,当我部署它时,我在 tokenEnhancer() 方法 SecurityConfig :

    org.springframework.beans.factory.BeanCreationException:
     Error creating bean with name 'tokenEnhancer' defined 
    in testproject.security.OAuth2Config: 
    Invocation of init method failed; nested exception is 
    java.lang.IllegalStateException: For MAC signing you 
    do not need to specify the verifier key separately, 
    and if you do it must match the signing key
            at org.springframework.beans.factory.support.
    AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1796)
            at org.springframework.beans.factory.support.
    AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595)
            at org.springframework.beans.factory.support.
    AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
            at org.springframework.beans.factory.support.
    AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
            
    

    我不知道该怎么修。

    SecurityConfig。JAVA :

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter  {
        private UserDetailsService userDetailsService;
        @Autowired
        private JwtRequestFilter jwtRequestFilter;
    
        public SecurityConfig(
                UserDetailsServiceImpl userDetailsService)  {
            this.userDetailsService = userDetailsService;
        }
    
        @Bean
        DaoAuthenticationProvider authenticationProvider(){
            DaoAuthenticationProvider daoAuthenticationProvider =
                    new DaoAuthenticationProvider();
            daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
            daoAuthenticationProvider.setUserDetailsService(this.userDetailsService);
            return daoAuthenticationProvider;
        }
    
        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring();
        }
        @Override
        @Bean
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }
    
        @Override
        @Autowired
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailsService)
                    .passwordEncoder(passwordEncoder());
        }
    
        @Override
        protected void configure(HttpSecurity httpSecurity) throws Exception {
            httpSecurity.csrf().disable()
                    .authorizeRequests().antMatchers("/authenticate")
                    .permitAll().
                    anyRequest().authenticated().and().
                    exceptionHandling()
                    .and().sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
            httpSecurity.addFilterBefore(jwtRequestFilter,
                    UsernamePasswordAuthenticationFilter.class);
        }
    
    
        @Bean
        PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
    }
    

    OAuth2Config。JAVA :

    @Configuration
    public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
        private String clientid = "tutorialspoint";
        private String clientSecret = "my-secret-key";
        private String privateKey = "private key";
        private String publicKey = "public key";
    
        @Autowired
        @Qualifier("authenticationManagerBean")
        private AuthenticationManager authenticationManager;
    
        @Bean
        public JwtAccessTokenConverter tokenEnhancer() {
            JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
            converter.setSigningKey(privateKey);
            converter.setVerifierKey(publicKey);
            return converter;
        }
    
        @Bean
        public JwtTokenStore tokenStore() {
            return new JwtTokenStore(tokenEnhancer());
        }
    
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints.authenticationManager(authenticationManager).tokenStore(tokenStore())
                    .accessTokenConverter(tokenEnhancer());
        }
    
        @Override
        public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
            security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
        }
    
        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.inMemory().withClient(clientid)
                    .secret(clientSecret).scopes("read", "write")
                    .authorizedGrantTypes("password", "refresh_token")
                    .accessTokenValiditySeconds(20000)
                    .refreshTokenValiditySeconds(20000);
        }
    }
    

    JwtRequestFilter。JAVA :

    @Component
    public class JwtRequestFilter extends OncePerRequestFilter {
        @Autowired
        private UserDetailsServiceImpl userDetailsService;
        @Autowired
        private JwtUtil jwtUtil;
    
        @Override
        protected void doFilterInternal(HttpServletRequest request,
                                        HttpServletResponse response, FilterChain chain)
                throws ServletException, IOException {
            final String authorizationHeader = request.getHeader("Authorization");
            String username = null;
            String jwt = null;
            if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
                jwt = authorizationHeader.substring(7);
                username = jwtUtil.extractUsername(jwt);
            }
    
            if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
                if (jwtUtil.validateToken(jwt, userDetails)) {
                    UsernamePasswordAuthenticationToken
                            usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
                            userDetails, null, userDetails.getAuthorities());
                    usernamePasswordAuthenticationToken
                            .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
                }
            }
            chain.doFilter(request, response);
        }
    }
    

    编辑 :

    我试图改变 privateKey 和 publicKey 要在线生成的值:

    private String privateKey = "-----BEGIN RSA PRIVATE KEY-----\n" +
                "Proc-Type: 4,ENCRYPTED\n" +
                "DEK-Info: DES-EDE3-CBC,A033B6E4DCA5218F\n" +
                "\n" +
                "QyTlIaijNU0EQi+DZKcihKNEDREpkG+14bKsrRh2NudDM42K37h6hQWNn859DYLT\n" +
                "J2mdF4ghs2PGZqxRukrsrfIA1VVFoTObGlLQCFXb1L+kH90vDEbB1qdxexedRJZF\n" +
                "NqQ9GXaGmUieGhBnMroSPshKvwmMzPXFcH/eYv/4RIKo9ejeWkx54NZtM1Boy2SE\n" +
                "lHGlZpVxEupKZ9fpw6bcr/TsA0cIuUHRtvf8lwgmBgKBXU9F8c2PhhVgalE2RcJv\n" +
                "q9ujFvF6FU9AtEZsV9+wJznoRrQlY447bnh9qlfI3JyGoz6czX9foeB70CWJM4TF\n" +
                "SZigb7TxhhBVtiIRsA5ILwXuSDQ0TDA08oG9WP5dQ0oplUkGa6AcEQnO4I9y4E3w\n" +
                "3UL314kndgxrgUF+IMDedfMxWHslFNGmz2VVibKtnOZEyjHZG1YqpUOqKP8WdJWS\n" +
                "OzOxkbydUtFoNPJ5V2rd/PNpI0t7sxTa2LUGpvHJXvSXTqQufp3ascnRTOpAQC2H\n" +
                "mjpRGx1SRIJA09WAfpIgGP5Ap6/cZIyZrgAlIQnGpDdOG9A5WRLPb6H2jUiDJnEv\n" +
                "ItNfDNj5fOQiL0tyBW5ulMBBNlRJxyP65XhU7H/6kn3AuW7Qg/znZTAIQnAr9rIY\n" +
                "eb4HUsF176ApezxeKLU+Z4fFNhxUFRB19/CHDjrKoaJxBoVwbH7bFOUP35BLPX5r\n" +
                "gSIlT6UJB/WEiewyhSNaYdvx0YLl7shsoLK/+62n0xoKd0zibDsWzTaNK5p06Mvt\n" +
                "JyHf86/iotOlvMZ/I+LQ7/yL4U1Z3AouZ9srG/VMeEXeHajfyg4Y9L8MTEESnQBV\n" +
                "N1IVCEHcUCg3EthAYWL/3OqcOwbNNfcUmLVH5INuAWyErPjKybCp6iW3ArAoPlUN\n" +
                "qAAqCDRI1V7qCV9nBNHMQlC8m7BuLwoD7kbNTHPOcuhM76ow+Y2jvrhJrkq/pbli\n" +
                "TwE5kDpOc6xIGVRmuxy2yYXmvppYv//GiepT89J0wCWacODVZF75yWO83556rGyn\n" +
                "rnqyMkDpZDqwRG3ktgWZNKDjAbbpcWmyFHobws/ZMKsXQiIuoU03smC3mCw1VMKa\n" +
                "YaRf6mEaa1pzNMqmQlD0aHWYN/9zeeMQHSTb7G2VeSB+yLmBvDeq6kyVoElx8Ark\n" +
                "2/lniftEhO85AAJz5hIEHSqi1MRzyxtb0qPjAB+NzFw2pgifVsEhqBPdvVhI1piZ\n" +
                "/nedPy808+GC/PF1BOR6S4ZdPFOUkRf4OLD3AbXTJsgYn1LAV2mC2lsUrnrWjhhT\n" +
                "jc41TmSue4FMf+s1ADntA+e9JB/uyePh5qrsLBqU6mjiIRf99nZ5qSqlgj6HuxWH\n" +
                "dGvgcZlTS1U5wsWSBDhrWXV703hQs3RSBCJshD44g5+iVneFLRO7fVeX+acK5A8k\n" +
                "+dc5ihVSsKI7wcchdrrta7MYdDNfd+6NlnCeKKhV9Mh9TheaxlVzmmKcUgMeLlqN\n" +
                "aGpojVX07F2HnoRah2Kq3h6C23g1RjO5zLVjJ5ZP5QcUKHqIHkv9Yxiy/IB0PPLp\n" +
                "jvMdn13O+KTiNQut/2IiOWpOIa0BgWVPbEZz5AUFIovztyFZOYDTPAidDGE8wxGK\n" +
                "-----END RSA PRIVATE KEY-----";
        private String publicKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCRGhJOZwdDh86Gaai3LLQfMTtNhvKjPElGeFXG/2FgWWRXRRZppAVLL8muWhzayt5mTl9a6eIhtH8qo1bJAdB+0fXErj4bx5ABaoU/O+jCLewLqRo13df+ryz9KLKoyB15JcEORMA6Izqp50mLGlw+vZn/cEc0deTC7GgqxmfzfH9VpbLr2GRB2HTk5oDZOE5uK99L7J5nOuSU7pGIu+RyOEWiXWX65i242wVvjdiBBEGCo1yHGZC7QX+UFHJMCAZzuyPbvnmxsbIkZJyelfQA3zzL8hmP0uEI8KJIqhCPG68FQ09U46G9yZOnOkywEum1sV8extcBtfeiYich1UK5";
    

    然而,现在的部署结果是

    org.springframework.beans.factory.BeanCreationException:
     Error creating bean with name 
    'tokenEnhancer' defined in testproject.security.OAuth2Config: 
    Bean instantiation via factory method failed;
     nested exception is org.springframework.beans.BeanInstantiationException: 
    Failed to instantiate [org.springframework.security.oauth2
    .provider.token.store.JwtAccessTokenConverter]:
     Factory method 'tokenEnhancer' threw exception;
     nested exception is org.springframework.security.jwt.codec
    .InvalidBase64CharacterException: 
    Bad Base64 input character decimal 45 in array position 5
            at
    

    错误

    感谢您的帮助。

    0 回复  |  直到 6 年前
        1
  •  0
  •   armandino    6 年前

    我认为问题是你在传递SSH公钥。首先需要生成密钥对,然后才能导出公钥:

    $ keytool -genkeypair -alias mytest -keyalg RSA -keypass changeit -keystore keystore.jks -storepass changeit
    $ keytool -list -rfc --keystore keystore.jks | openssl x509 -inform pem -pubkey > pubkey.txt
    

    您可以加载密钥:

    KeyPair keyPair = new KeyStoreKeyFactory(
        new ClassPathResource("keystore.jks"), "changeit".toCharArray())
            .getKeyPair("mytest");
    

    您的授权服务器将使用上述 KeyPair 要签名,资源服务器将使用公钥。