Spring Boot OAuth2 - 使用自定义过滤器对Facebook进行身份验证

时间:2016-06-28 14:09:06

标签: angularjs spring facebook oauth-2.0 spring-social

我正在研究Rest Api,我想在我的应用程序中实现facebook登录/注册。 我的客户端是基于angularjs的应用程序,它向facebook发送请求并获取身份验证代码,到目前为止,我使用自定义过滤器调用facebook并在验证访问令牌后获取用户数据。

我现在可以从Facebook获取用户详细信息并保留在我的本地数据库中,但是当我尝试从我的应用程序注册时,它会移动到我为facebook集成进行的自定义过滤器。这是我的SecurityConfiguration.java

package io.aurora.ams.config;

import io.aurora.ams.security.AuthoritiesConstants;
import io.aurora.ams.web.filter.MDCFilter;
import org.springframework.boot.context.embedded.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.data.repository.query.SecurityEvaluationContextExtension;
import org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter;
import org.springframework.security.web.context.SecurityContextPersistenceFilter;

import javax.inject.Inject;

import static io.aurora.ams.sharedkernel.support.RestPath.*;

@Configuration
@EnableWebSecurity(debug = true)
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@ImportResource("classpath:acl-config.xml")
@SuppressWarnings("ALL")
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
    @Bean
    public AuthFilter authFilter()
    {
        return new AuthFilter();
    }

    @Inject
    private UserDetailsService userDetailsService;

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

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

    @Bean
    public MDCFilter mdcFilter()
    {
        return new MDCFilter();
    }
    @Bean
    public FilterRegistrationBean mySecurityFilter()
    {
        FilterRegistrationBean registration = new FilterRegistrationBean(authFilter());
        registration.setOrder(10);
        return registration;
    }
    @Override
    public void configure(WebSecurity web) throws Exception
    {
        web.ignoring()
            .antMatchers(HttpMethod.OPTIONS, "/**")
            .antMatchers(API_VERSION_1_ACCOUNT_REGISTER_PATIENT)
            .antMatchers(API_VERSION_1_ACCOUNT_ACTIVATE)
            .antMatchers(API_VERSION_1_ACCOUNT_RECOVER_PASSWORD)
            .antMatchers("/test/**")
            .antMatchers("/h2-console/**");
    }

    @Override
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public void configure(HttpSecurity http) throws Exception
    {
        http
            .addFilterBefore(authFilter(), OAuth2ClientAuthenticationProcessingFilter.class)
            .addFilterAfter(mdcFilter(), SecurityContextPersistenceFilter.class)
            .httpBasic().realmName("pliro")
            .and()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()


            .authorizeRequests()
                .antMatchers("/oauth/authorize").permitAll()
                .antMatchers("api/v1/auth/facebook").permitAll()
                .antMatchers("api/v1/code").permitAll()
            .and()
            .authorizeRequests()
            .antMatchers(API_VERSION_1_DOCTOR).permitAll()
            .antMatchers(API + "/**").authenticated();
    }

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

    @Bean
    public SecurityEvaluationContextExtension securityEvaluationContextExtension()
    {
        return new SecurityEvaluationContextExtension();
    }
}

这是我的CustomFilter AuthFilter.java

package io.aurora.ams.config;

import io.aurora.ams.account.domain.model.user.User;
import io.aurora.ams.account.dto.UserDTO;
import io.aurora.ams.account.mapper.UserMapper;
import io.aurora.ams.account.repository.UserRepository;
import io.aurora.ams.sharedkernel.domain.model.Gender;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.social.InvalidAuthorizationException;
import org.springframework.social.connect.Connection;
import org.springframework.social.facebook.api.Facebook;
import org.springframework.social.facebook.connect.FacebookConnectionFactory;
import org.springframework.social.oauth2.AccessGrant;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.inject.Inject;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Created by ozair on 16/6/16.
 */
@Component
public class AuthFilter extends OncePerRequestFilter
{

    @Autowired
    private UserRepository userRepository;
    @Autowired
    private FacebookConnectionFactory facebookConnectionFactory;

    @Inject
    private UserMapper userMapper;

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response, FilterChain filterChain)
        throws ServletException, IOException
    {

        String xAuth = request.getHeader("fbToken");

        try
        {
            User user = validateToken(xAuth);

            // Create our Authentication and let Spring know about it
            Authentication authentication = new UsernamePasswordAuthenticationToken(user, null, AuthorityUtils.createAuthorityList("ROLE_USER"));
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
        catch (InvalidAuthorizationException ex)
        {
            logger.error(ex.getMessage());
        }

        filterChain.doFilter(request, response);
    }

    private User validateToken(String fbToken)
    {
        AccessGrant accessGrant = new AccessGrant(fbToken);
        Connection<Facebook> connection = facebookConnectionFactory.createConnection(accessGrant);
        org.springframework.social.facebook.api.User fbUser = connection.getApi().userOperations().getUserProfile();

        String facebookId = fbUser.getId();
        User user = userRepository.findBySocialId(facebookId);
        if (user == null)
        {
            User userByEmail = userRepository.findByEmail(fbUser.getEmail());
            if (userByEmail != null)
            {
                userByEmail.setSocialAccessGrant(accessGrant.getAccessToken());
                userByEmail.setSocialId(facebookId);
                userRepository.save(userByEmail);
                return userByEmail;
            }
            else
            {
                String firstName = fbUser.getFirstName();
                String lastName = fbUser.getLastName();
                String email = fbUser.getEmail() == null ? "" : fbUser.getEmail();
                UserDTO userDTO = new UserDTO();
                userDTO.setFirstName(firstName);
                userDTO.setLastName(lastName);
                userDTO.setEmail(email);
                userDTO.setPassword("123456");
                userDTO.setPhoneNumber("03222211112");

                userDTO.setGender(Gender.MALE);
                userDTO.setSocialId(facebookId);
                userDTO.setAccessGrant(accessGrant);
                User userData = userMapper.userDTOtoUser(userDTO);
                userRepository.save(userData);
                return userData;
            }
        }
        else
        {
            //update fbToken if not the same
            if (user.getSocialAccessGrant() != null
                && !user.getSocialAccessGrant().equals(accessGrant.getAccessToken()))
            {
                user.setSocialAccessGrant(accessGrant.getAccessToken());
                userRepository.save(user);
            }
            return user;
        }


    }

}

0 个答案:

没有答案