具有oauth和带有表单登录功能的UI的Secure Rest API

时间:2019-08-07 06:06:21

标签: spring-boot spring-security spring-security-oauth2

我正在尝试为两个端点/api/admin配置安全性。 对于/api,我想使用基于jwt令牌的无状态机制进行保护,而对于/admin,我想使用基于表单的登录。

Spring security oauth2 and form login configuration上已经找到其他人之后,我尝试配置它。 会根据我为配置设置的/admin来使我的/api受保护或@Order受保护。

一些关于整数值的排序是如何无效的。必须使用org.springframework.core.Ordered进行设置,然后只有资源服务器配置获得优先级

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;

@EnableWebSecurity
public class MultiHttpSecurityConfig {

    @Autowired
    private CustomUserDetailsService userDetailsService;

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

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

    @Configuration
    @EnableWebSecurity
    public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {

        Logger logger = LoggerFactory.getLogger(ApiWebSecurityConfigurationAdapter.class);

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

            logger.info("\n---------\n m here ApiWebSecurityConfigurationAdapter\n---------\n");
            http.authorizeRequests().antMatchers("/api/**").hasRole("USER").and().formLogin();
        }

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

    }

    @Configuration
    @Order(1)
    public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

        Logger logger = LoggerFactory.getLogger(FormLoginWebSecurityConfigurerAdapter.class);

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            logger.info("\n---------\n m here FormLoginWebSecurityConfigurerAdapter\n---------\n");

            http.csrf().disable().authorizeRequests().antMatchers("/admin/**")
                    .hasAnyAuthority("admin", "ADMIN_USER").and().formLogin().permitAll().and().logout().permitAll();
        }
    }

    @Configuration
    @EnableResourceServer
    @Order(2)
    public class CustomResourceServerConfigurerAdapter extends ResourceServerConfigurerAdapter {

        Logger logger = LoggerFactory.getLogger(CustomResourceServerConfigurerAdapter.class);

        @Autowired
        private JdbcTemplate jdbcTemplate;

        @Bean
        public TokenStore tokenStore() {
            return new JdbcTokenStore(jdbcTemplate.getDataSource());
        }

        @Bean
        @Primary
        //Making this primary to avoid any accidental duplication with another token service instance of the same name
        public DefaultTokenServices tokenServices() {
            DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
            defaultTokenServices.setTokenStore(tokenStore());
            defaultTokenServices.setSupportRefreshToken(true);
            return defaultTokenServices;
        }

        @Override
        public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
            resources.tokenServices(tokenServices());
        }

        @Override
        public void configure(HttpSecurity http) throws Exception {

            logger.info("\n---------\n m here CustomResourceServerConfigurerAdapter\n---------\n");

            http.authorizeRequests()
                        .and()
                        .anonymous().disable()
                        .sessionManagement()
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                        .and().httpBasic()
                        .and()
                        .authorizeRequests()
                        .antMatchers("/api/**").fullyAuthenticated();

        }
    }

}

和我的OAuth2Configuration

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;

@Configuration
@EnableAuthorizationServer
public class OAuth2Configuration extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired 
    private CustomUserDetailsService userDetailsService;

    @Autowired
    private TokenStore tokenStore;

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        return new JwtAccessTokenConverter();
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.tokenKeyAccess("hasAuthority('ROLE_TRUSTED_CLIENT')")
                .checkTokenAccess("hasAuthority('ROLE_TRUSTED_CLIENT')");
    }

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

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

}

我希望同时保护两个端点,即使用jwt令牌保护/api并使用基于表单的登录保护/admin。我不想为Rest API和UI实施2个不同的项目

编辑

感谢@dur睁大了眼睛

我能够使用

保护我的其余api
@Override
public void configure(HttpSecurity http) throws Exception {

    logger.info("\n---------\n m here CustomResourceServerConfigurerAdapter\n---------\n");

    http
        .antMatcher("/api/**")
        .authorizeRequests()
            .antMatchers("/api/**" ).authenticated();

}

但是我无法保护自己的/admin,除非使用httpBasic

如果有人可以告诉我如何配置表单登录名,将非常有帮助

@Override
protected void configure(HttpSecurity http) throws Exception {
    logger.info("\n---------\n m here FormLoginWebSecurityConfigurerAdapter\n---------\n");


            http
            .antMatcher("/admin/**")
            .authorizeRequests()
                .anyRequest().hasAnyAuthority("ADMIN_USER")
                .and()
            .httpBasic();
}

我尝试过

http.antMatcher("/admin/**").authorizeRequests()
    .antMatchers("/admin/**").hasAnyAuthority("ADMIN_USER")
    .and()
        .formLogin()
            .permitAll()
    .and()
        .logout()
            .permitAll();

但这没用

编辑2

最终明白了

http
    .antMatcher("/admin/**")
    .authorizeRequests()
        .anyRequest().hasAnyAuthority("ADMIN_USER")
    .and()
        .formLogin()
        .loginPage("/admin/login")
        .permitAll()
    .and()
        .logout()
            .logoutUrl("/admin/logout")
            .invalidateHttpSession(true)
            .permitAll();

http.csrf().disable();

0 个答案:

没有答案