Spring Security OAuth2的Web和移动客户端

时间:2015-08-12 15:59:50

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

我试图围绕OAuth2和Spring Security OAuth,尤其是OAuth提供商服务。我试图实施以下内容:

  1. OAuth提供商
  2. 资源服务器(应使用OAuth Provider(1)保护的RESTful Web服务)
  3. Web客户端(使用Spring Security保护但应使用OAuth Provider(1)对用户进行身份验证的Web客户端应用程序
  4. 原生移动客户端(Android和iOS)也应使用OAuth Provider(1)进行身份验证
  5. 所有这些模块彼此独立,即在不同的项目中分开,并将托管在不同的域上,例如(1)http://oauth.web.com,(2)http://rest.web.com,(3){{ 3}}

    我的两个问题是:

    一个。如何实现Web客户端项目,以便在用户登录受保护页面或单击“登录”按钮时,重定向到OAuth提供程序URL,登录,并在具有所有用户角色的Web客户端上进行身份验证,以及需要知道使用了哪个客户端。在此项目中@EnableResourceServer(与资源服务器实现的方式相同;请参阅下面的代码)以获取用户的详细信息?我是否必须管理访问令牌并始终将其包含在对资源服务器的调用中,或者可以以某种方式自动完成?

    B中。在我正在开发的移动应用程序上实现安全性的最佳方法是什么。我是否应该使用密码grand进行此身份验证,因为应用程序将由我构建,我将在本机屏幕中使用用户名和密码,然后通过SSL将其作为基本身份验证发送到服务器?是否有任何示例我可以查看与Spring Security OAuth的对话并返回用户详细信息。

    这是我对OAuth项目(1)和资源项目(2)的实现:

    1。 OAuth提供商

    OAuth2服务器配置(大部分代码来自http://web.com

    @Configuration
    @EnableAuthorizationServer
    public class OAuth2ServerConfig extends AuthorizationServerConfigurerAdapter {
    
        @Autowired
        @Qualifier("authenticationManagerBean")
        private AuthenticationManager authenticationManager;
    
        @Autowired
        DataSource dataSource;
    
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints
                    .tokenStore(tokenStore())
                    .approvalStore(approvalStore())
                    .authorizationCodeServices(authorizationCodeServices())
            ;
        }
    
        @Bean
        public JdbcClientDetailsService clientDetailsService() {
            return new JdbcClientDetailsService(dataSource);
        }
    
        @Bean
        public TokenStore tokenStore() {
            return new JdbcTokenStore(dataSource);
        }
    
        @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());
        }
    
        @Override
        public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
    
            oauthServer.checkTokenAccess("permitAll()");
        }
    }
    

    网络安全配置

    @Configuration
    @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
    
        @Autowired
        private CustomUserDetailsService customUserDetailsService;
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
    
            http.csrf().disable(); // TODO. Enable this!!!
    
            http.authorizeRequests()
                    .and()
                    .formLogin()
    //                .loginPage("/login") // manually defining page to login
    //                .failureUrl("/login?error") // manually defining page for login error
                    .usernameParameter("email")
                    .permitAll()
    
                    .and()
                    .logout()
    //                .logoutUrl("/logout")
                    .logoutSuccessUrl("/")
                    .permitAll();
        }
    
        @Override
        public void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth
                    .userDetailsService(customUserDetailsService)
                    .passwordEncoder(new BCryptPasswordEncoder());
        }
    
        @Override
        @Bean
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }
    }
    

    UserDetailsS​​ervice(customUserDetailsS​​ervice)

    @Service
    public class CustomUserDetailsService implements UserDetailsService{
    
        private final UserService userService;
    
        @Autowired
        public CustomUserDetailsService(UserService userService) {
            this.userService = userService;
        }
    
        public Authority loadUserByUsername(String email) throws UsernameNotFoundException {
            User user = userService.getByEmail(email)
                    .orElseThrow(() -> new UsernameNotFoundException(String.format("User with email=%s was not found", email)));
            return new Authority(user);
        }
    }
    

    2。资源服务器(RESTful WS)

    配置(大多数框架代码来自HERE示例)

    @Configuration
    @EnableResourceServer
    public class OAuth2ResourceConfig extends ResourceServerConfigurerAdapter{
    
        @Autowired
        DataSource dataSource;
    
        String RESOURCE_ID = "data_resource";
    
        @Override
        public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
            TokenStore tokenStore = new JdbcTokenStore(dataSource);
            resources
                    .resourceId(RESOURCE_ID)
                    .tokenStore(tokenStore);
        }
    
        @Override
        public void configure(HttpSecurity http) throws Exception {
            http
                    // For some reason we cant just "permitAll" OPTIONS requests which are needed for CORS support. Spring Security
                    // will respond with an HTTP 401 nonetheless.
                    // So we just put all other requests types under OAuth control and exclude OPTIONS.
                    .authorizeRequests()
                    .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()
    
                    // Add headers required for CORS requests.
                    .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"));
                }
            });    
        }
    }
    

    WS Controller:

    @RestController
    @RequestMapping(value = "/todos")
    public class TodoController {
    
        @Autowired
        private TodoRepository todoRepository;
    
        @RequestMapping(method = RequestMethod.GET)
        public List<Todo> todos() {
            return todoRepository.findAll();
        }
    
       // other methods
    }
    

0 个答案:

没有答案