在服务器端设置基本身份验证

时间:2019-01-16 17:21:46

标签: java rest spring-security spring-security-oauth2

我在一个应用程序中配置了资源和授权服务器。我使用带有资源所有者密码凭证的spring-security oauth2。我可以在服务器端设置基本身份验证吗?我不想在前端做。 我不知道我需要显示的代码的哪一部分... 当我想接收令牌时,需要在邮递员中输入该令牌: from postman 我可以在服务器端配置它吗?

授权服务器:

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private DataSource dataSource;

    @Autowired
    private TokenStore tokenStore;

    @Autowired
    private JwtAccessTokenConverter jwtTokenEnhancer;

    @Autowired
    private UserApprovalHandler userApprovalHandler;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.jdbc(dataSource);
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) {
        security.checkTokenAccess("isAuthenticated()");
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore).tokenEnhancer(jwtTokenEnhancer).userApprovalHandler(userApprovalHandler)
                .authenticationManager(authenticationManager)
                .pathMapping("/oauth/token", "/login");
    }
}

资源服务器:

@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
                .cors().and().csrf().disable()

                .authorizeRequests()
                .antMatchers("/swagger-ui.html#").permitAll()
                .antMatchers("/").authenticated()
                .and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
    }
}

安全配置:

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

    @Autowired
    private ClientDetailsService clientDetailsService;

    @Autowired
    private CustomAuthenticationProvider customAuthenticationProvider;

    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder(10);
    }


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


    @Override
    public void configure(final AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(customAuthenticationProvider);
    }


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

    @Bean
    protected JwtAccessTokenConverter jwtTokenEnhancer() {
        converter.setSigningKey("Demo-Key-1");
        return converter;
    }

    @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;
    }

    @Override
    @Order(Ordered.HIGHEST_PRECEDENCE)
    protected void configure(final HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/resources/**").permitAll()
                .antMatchers(HttpMethod.OPTIONS, "/oauth/token").permitAll()
                .and().cors().and().csrf().disable();
    }
}

1 个答案:

答案 0 :(得分:2)

此答案附有complete and working sample

也许您biting off more than you can chew在这里?

例如:

.antMatchers(HttpMethod.OPTIONS, "/oauth/token").permitAll()

/oauth/token端点必须保持受保护的状态。这是授权服务器上的端点,该端点向已认证的客户端颁发令牌。如果您打开系统,则系统可能会因NullpointerException或其他异常而失败,但是,上述配置选项表明您可能对OAuth2的工作方式有些困惑。

我建议您首先完全了解授权服务器与资源服务器。您当然可以将两者结合起来,但是它们的端点将完全不同。

授权服务器-典型端点

/oauth/token - issues tokens
/oauth/authorize - issues authorization codes
/introspect - validates a token and returns token claims in a known format

资源服务器-这些将是您的应用程序端点,例如,需要Bearer令牌

/account/123/debit

并且这些端点期望具有授权标头的无状态请求

Authorization: Bearer <token value here>

资源服务器的控制器如下所示:

@PreAuthorize("hasRole('your-scope-role')")
@RequestMapping(value = "/hello")
@ResponseBody
public String hello(Principal principal) {
    return "Hello to " + principal.getName();
}

随时查看我为您创建的simple project

除此之外,我还在OAuth2 and OpenID Connect

上推荐了该视频

在我的示例中,我像这样配置clients

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        InMemoryClientDetailsService clientDetails = new InMemoryClientDetailsService();
        BaseClientDetails client = new BaseClientDetails(
            "testclient",
            null,
            "testscope,USER,ADMIN",
            "password",
            null
        );
        client.setClientSecret(passwordEncoder.encode("secret"));
        clientDetails.setClientDetailsStore(
            Collections.singletonMap(
                client.getClientId(),
                client
            )
        );
        clients.withClientDetails(clientDetails);
    }

看看这个简单的测试用例,客户端正在使用http-basic身份验证:

mvc.perform(
    post("/oauth/token")
            .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
            .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
            .param("username", "admin")
            .param("password", "password")
            .param("grant_type", "password")
            .param("response_type", "token")
            .param("client_id", "testclient")
            .header("Authorization", "Basic " + Base64.encodeBase64String("testclient:secret".getBytes()))

这是使用http-basic方法的客户端身份验证:

.header("Authorization", "Basic " + Base64.encodeBase64String("testclient:secret".getBytes()))