【问题标题】:Spring boot endpoint is not authenticatedSpring Boot 端点未经过身份验证
【发布时间】:2019-02-10 04:20:58
【问题描述】:

我正在努力学习 oauth2jwt 所以我的参考链接是

https://www.devglan.com/spring-security/spring-boot-oauth2-jwt-example

我正在使用spring boot 1.5.15

AuthorizationServerConfig

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    static final String CLIEN_ID = "devglan-client";
    static final String CLIENT_SECRET = "devglan-secret";
    static final String GRANT_TYPE_PASSWORD = "password";
    static final String AUTHORIZATION_CODE = "authorization_code";
    static final String REFRESH_TOKEN = "refresh_token";
    static final String IMPLICIT = "implicit";
    static final String SCOPE_READ = "read";
    static final String SCOPE_WRITE = "write";
    static final String TRUST = "trust";
    static final int ACCESS_TOKEN_VALIDITY_SECONDS = 1*60;
    static final int FREFRESH_TOKEN_VALIDITY_SECONDS = 6*60*60;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey("as466gf");
        return converter;
    }

    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(accessTokenConverter());
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer configurer) throws Exception {

        configurer
                .inMemory()
                .withClient(CLIEN_ID)
                .secret(CLIENT_SECRET)
                .authorizedGrantTypes(GRANT_TYPE_PASSWORD, AUTHORIZATION_CODE, REFRESH_TOKEN, IMPLICIT )
                .scopes(SCOPE_READ, SCOPE_WRITE, TRUST)
                .accessTokenValiditySeconds(ACCESS_TOKEN_VALIDITY_SECONDS).
                refreshTokenValiditySeconds(FREFRESH_TOKEN_VALIDITY_SECONDS);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore())
                .authenticationManager(authenticationManager)
                .accessTokenConverter(accessTokenConverter());
    }
}

资源服务器配置

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    private static final String RESOURCE_ID = "resource_id";

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources.resourceId(RESOURCE_ID).stateless(false);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.
                anonymous().disable()
                .authorizeRequests()
                .antMatchers("/users").access("hasRole('SCT_USER')")
                .and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
    }

}


    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class SecurityConfig extends WebSecurityConfigurerAdapter {


        @Autowired
        private SecurityHandler securityHandler;

        @Autowired
        private UserSecurityService userSecurityService;


        private static final String[] PUBLIC_MATCHERS = {
                "/css/**",
                "/js/**",
                "/images/**",
                "/",
                "**/",
                "/newUser",
                "/forgetPassword",
                "/login",
                "**/uploads/**",
                "/assets/**",
                "/api/updateCardStatus",
                "/fonts/**",
                "/users"
        };

       /* @Override
        protected void configure(HttpSecurity http) throws Exception {

            http
                    .authorizeRequests()

                    *//*    antMatchers("/**").*//*
                    .antMatchers(PUBLIC_MATCHERS).
                    permitAll().anyRequest().authenticated();

            http
                    .authorizeRequests()
                    .antMatchers("/admin").hasAnyRole("ROLE_ADMIN").and()
                    .formLogin().loginPage("/login").permitAll().failureUrl("/login?error")
                    .successHandler(securityHandler)
                    .and()
                    .logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                    .logoutSuccessUrl("/?logout").deleteCookies("remember-me").permitAll()
                    .and()
                    .rememberMe();
        }*/

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .csrf().disable()
                    .anonymous().disable()
                    .authorizeRequests()
                    .antMatchers("/api-docs/**").permitAll();
        }



        @Override
        public void configure(WebSecurity web) throws  Exception{
            web.ignoring()
                    .antMatchers("/api/updateCardStatus","*/uploads/***","/api/getUsersDetail","/api/getStudentDetails","/api/getAccountLoad","/api/issueDirectives","/api/changePassword","/api/cardActivation","/api/CustomerAccountCardDetails","/api/accountLoad","/api/updateConsumersProfile","/api/verifyCvv"
                            ,"/api/updatePrepaidCardStatus","/api/getStatementData");
        }

        @Override
        @Bean
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }


        @Autowired
        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userSecurityService).passwordEncoder(SecurityUtils.passwordEncoder());
        }


    @Bean
    public BCryptPasswordEncoder encoder(){
        return new BCryptPasswordEncoder();
    }

    @Bean
    public FilterRegistrationBean corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(0);
        return bean;
    }
}

现在当我调用这些配置时

http://localhost:8080/oauth/token

这让我可以访问和刷新这是我想要的。但是现在

我有一个看起来像这样的控制器

 @GetMapping("/users")
    public Map<String,String> getUsers(){
        Map<String,String> map = new HashMap<>();
        map.put("name","sagar");
        map.put("job","developers");
        return map;
    }

所以我这样称呼这个端点

http://localhost:8080/users

现在我期望的是,每当我调用这个端点时,这个调用都应该被验证。但它只是返回我

{
    "name": "sagar",
    "job": "developers"
}

即使我不发送任何令牌。我希望这个端点被允许使用角色SCT_USER

为什么这没有发生?

【问题讨论】:

    标签: java spring-boot oauth-2.0 jwt


    【解决方案1】:

    请仔细查看我的SecurityConfig版本

    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private ClientDetailsService clientDetailsService;
    
    /*@Autowired
    private SecurityHandler securityHandler;
    
    @Autowired
    private UserSecurityService userSecurityService;
    */
    
    private static final String[] PUBLIC_MATCHERS = {
            "/css/**",
            "/js/**",
            "/images/**",
            "/",
            "**/",
            "/newUser",
            "/forgetPassword",
            "/login",
            "**/uploads/**",
            "/assets/**",
            "/api/updateCardStatus",
            "/fonts/**",
            "/users"
    };
    
       /* @Override
        protected void configure(HttpSecurity http) throws Exception {
    
            http
                    .authorizeRequests()
    
                    *//*    antMatchers("/**").*//*
                    .antMatchers(PUBLIC_MATCHERS).
                    permitAll().anyRequest().authenticated();
    
            http
                    .authorizeRequests()
                    .antMatchers("/admin").hasAnyRole("ROLE_ADMIN").and()
                    .formLogin().loginPage("/login").permitAll().failureUrl("/login?error")
                    .successHandler(securityHandler)
                    .and()
                    .logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                    .logoutSuccessUrl("/?logout").deleteCookies("remember-me").permitAll()
                    .and()
                    .rememberMe();
        }*/
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .anonymous().disable()
                .authorizeRequests()
                .antMatchers("/api-docs/**").permitAll().anyRequest().authenticated();
    }
    
    
    
    @Override
    public void configure(WebSecurity web) throws  Exception{
        web.ignoring()
                .antMatchers("/api/updateCardStatus","*/uploads/***","/api/getUsersDetail","/api/getStudentDetails","/api/getAccountLoad","/api/issueDirectives","/api/changePassword","/api/cardActivation","/api/CustomerAccountCardDetails","/api/accountLoad","/api/updateConsumersProfile","/api/verifyCvv"
                        ,"/api/updatePrepaidCardStatus","/api/getStatementData");
    }
    
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
    
    @Autowired
    public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("admin")
                .password("pass")
                .roles("ADMIN", "USER").and()
                .withUser("appuser")
                .password("pass123").roles("USER");
    }
    
    /*@Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userSecurityService).passwordEncoder(SecurityUtils.passwordEncoder());
    }*/
    
    
    @Bean
    public PasswordEncoder encoder(){
        return NoOpPasswordEncoder.getInstance();
    }
    
    @Bean
    public FilterRegistrationBean corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(0);
        return bean;
    }
    
    @Bean
    @Autowired
    public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore) {
        TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
        handler.setTokenStore(tokenStore);
        handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
        handler.setClientDetailsService(clientDetailsService);
        return handler;
    }
    
    @Bean
    @Autowired
    public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception {
        TokenApprovalStore store = new TokenApprovalStore();
        store.setTokenStore(tokenStore);
        return store;
    }
    
    
    }
    

    这里有两个重点

    @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
    

    还有

    @Override
    protected void configure(HttpSecurity http) throws Exception {
    http
            .csrf().disable()
            .anonymous().disable()
            .authorizeRequests()
            .antMatchers("/api-        docs/**").permitAll().anyRequest().authenticated();
    }
    

    别忘了在你有 access("hasRole('SCT_USER')") 的 ResourceServerConfig 中修正你的错字

    而不是

    access("hasRole('USER')")
    

    我已经为您的代码创建了测试示例。 https://github.com/alex-petrov81/stackoverflow-answers/tree/master/spring-boot-endpoint-not-auth

    【讨论】:

    • 不是我已经提供了Securityconfig类的代码
    • 仔细检查您的代码后,我发现了一个错误:hasRole('SCT_USER'),但在您的凭据中,您使用的是 USER 角色。我很快就会改变我的答案
    • 这修复了它。非常感谢。我花了几个小时,我仍然无法检测到它们。这个@Order 注解有什么作用?
    • 在 1.5.x 版本之后 OAuth2 资源服务器顺序设置为 SecurityProperties.ACCESS_OVERRIDE_ORDER - 1 现在其优先级肯定低于基本的 WebSecurityConfigurerAdapter 顺序。所以它导致指定 @Order 注释来恢复 WebSecurityConfigurerAdapter 顺序。它在 Spring 过滤器链中启用 OAuth 过滤器。
    • 看来这个订单的东西弄乱了我的其他网址。就像我打电话给 localhost:8080/admin 它之前打开了 admin.html 页面。但在保留订单注释后,它现在返回一些 xml 错误。我怎么说例如localhost:8080/api**(将其视为api),剩余的url是正常的重定向url
    猜你喜欢
    • 2020-08-02
    • 1970-01-01
    • 2021-11-04
    • 2017-07-30
    • 2020-01-15
    • 2017-04-17
    • 2019-09-07
    • 2022-11-01
    • 2019-02-21
    相关资源
    最近更新 更多