简体   繁体   English

如何通过Spring Social Facebook注册新用户?

[英]How to sign up new user via Spring Social Facebook?

I am having a website (Angular App) which I can reach on https://localhost:4200 and a server (pure REST API) that is on https://localhost:8443 . 我有一个网站(Angular App),我可以通过https:// localhost:4200https:// localhost:8443上的服务器(纯REST API)访问。

Since the REST endpoints are secured, a user must login on my server. 由于REST端点是安全的,因此用户必须在我的服务器上登录。 Obviously I want users to be able to signup using Facebook and further communicate with my server after login. 显然,我希望用户能够使用Facebook注册,并在登录后进一步与我的服务器通信。


According to the docs 根据文件

POST /signin/{providerId} - Initiates the sign in flow. POST /signin/{providerId} - 启动登录流程。

that is why there is a button that does just this: 这就是为什么有一个按钮可以做到这一点:

<form ngNoForm name="fb_signin" id="fb_signin" action="https://localhost:8443/signin/facebook" method="POST">
  <input type="hidden" name="scope" value="email">
  <button type="submit">SIGNING</button>
</form>

From there, everything works fine for some time. 从那里,一切都运行正常一段时间。 The user gets redirected to Facebook's authorization page where the authorization button gets clicked. 用户被重定向到Facebook的授权页面,其中点击了授权按钮。 After that the user gets redirected to https://localhost:8443/signin/facebook . 之后,用户被重定向到https:// localhost:8443 / signin / facebook


It seems that per default, in case the user is unknown, there will be a another redirect to https://localhost:8443/signup ( see docs ) 似乎默认情况下,如果用户未知,将会有另一个重定向到https:// localhost:8443 / signup参见docs

If the provider user ID matches more than one existing connection, ProviderSignInController will redirect to the application's sign in URL to offer the user a chance to sign in through another provider or with their username and password. 如果提供者用户ID与多个现有连接匹配,则ProviderSignInController将重定向到应用程序的登录URL,以便为用户提供通过其他提供者或其用户名和密码登录的机会。 The request to the sign in URL will have an " error " query parameter set to " multiple_users " to indicate the problem so that the page can communicate it to the user. 对登录URL的请求将“ error ”查询参数设置为“ multiple_users ”以指示问题,以便页面可以将其传达给用户。 The default sign in URL is " /signin " (relative to the application root), but can be customized by setting the signInUrl property. 默认登录URL为“ /signin ”(相对于应用程序根目录),但可以通过设置signInUrl属性进行自定义。

On my serer this looks like this ( borrowed from a sample application ): 在我的服务器上,这看起来像这样( 从示例应用程序中借用 ):

@RequestMapping(value = "/signup", method = RequestMethod.GET)
public SignUpForm signupForm(WebRequest request) {
    Connection<?> connection = providerSignInUtils.getConnectionFromSession(request);
    if (connection != null) {
        request.setAttribute("message", new Message(MessageType.INFO, "Your " + StringUtils.capitalize(connection.getKey().getProviderId()) + " account is not associated with a Spring Social Showcase account. If you're new, please sign up."), WebRequest.SCOPE_REQUEST);
        return SignUpForm.fromProviderUser(connection.fetchUserProfile());
    } else {
        return new SignUpForm();
    }
}

And here are my issues: 以下是我的问题:

First of all I need to know what I am supposed to do at this endpoint. 首先,我需要知道我应该在这个端点做什么。 The user authorized my app, but my server does not know the user yet so do I 用户授权我的应用程序,但我的服务器不知道用户,所以我也是

  • connection.fetchUserProfile() and save the new user to my database connection.fetchUserProfile()并将新用户保存到我的数据库
  • something else? 别的什么?

Second, I do not know how I am supposed to redirect back to my website from here which, as explained, lies on https://localhost:4200 . 其次,我不知道我应该如何从这里重定向回我的网站,正如所解释的那样,它位于https:// localhost:4200 But of course, my server does not know that. 但是,当然,我的服务器不知道这一点。

Is there a chance somebody can guide me through this? 是否有人可以指导我完成这项工作?


This is the SocialConfig 这是SocialConfig

@Configuration
@EnableSocial
public class SocialConfig implements SocialConfigurer {

    private final static Logger LOGGER = LogManager.getLogger(SocialConfig.class);

    @Value("${spring.social.facebook.appId}")
    String facebookAppId;

    @Value("${spring.social.facebook.appSecret}")
    String facebookSecret;

    @Autowired
    private DataSource dataSource;

    @Bean
    @Scope(value="singleton", proxyMode = ScopedProxyMode.INTERFACES)
    public ConnectionFactoryLocator connectionFactoryLocator() {
        ConnectionFactoryRegistry registry = new ConnectionFactoryRegistry();

        registry.addConnectionFactory(new FacebookConnectionFactory(
                facebookAppId,
                facebookSecret
        ));

        return registry;
    }

    @Bean
    @Scope(value="singleton", proxyMode=ScopedProxyMode.INTERFACES)
    public UsersConnectionRepository usersConnectionRepository() {
        return new JdbcUsersConnectionRepository(dataSource, connectionFactoryLocator(), Encryptors.noOpText());
    }

    @Override
    public void addConnectionFactories(ConnectionFactoryConfigurer cfConfig, Environment env) {
        LOGGER.debug("Adding connection factories");
        cfConfig.addConnectionFactory(new FacebookConnectionFactory(
                env.getProperty("facebook.clientId"),
                env.getProperty("facebook.clientSecret")));

    }

    @Override
    public UserIdSource getUserIdSource() {
        return new AuthenticationNameUserIdSource();
    }

    @Override
    public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
        return new JdbcUsersConnectionRepository(dataSource, connectionFactoryLocator, Encryptors.noOpText());
    }

    @Bean
    public ProviderSignInController providerSignInController(
            ConnectionFactoryLocator connectionFactoryLocator,
            UsersConnectionRepository usersConnectionRepository) {
        ProviderSignInController controller = new ProviderSignInController(
                connectionFactoryLocator,
                usersConnectionRepository,
                new SimpleSignInAdapter(new HttpSessionRequestCache()));

        return controller;
    }

    @Bean
    public RequestCache requestCache() {
        return new HttpSessionRequestCache();
    }

    @Bean
    public SignInAdapter signInAdapter() {
        return new SimpleSignInAdapter(new HttpSessionRequestCache());
    }

}

Maven dependencies related to Spring Social: 与Spring Social相关的Maven依赖项:

<dependency>
    <groupId>org.springframework.social</groupId>
    <artifactId>spring-social-facebook</artifactId>
    <version>3.0.0.M1</version>
</dependency>
<dependency>
    <groupId>org.springframework.social</groupId>
    <artifactId>spring-social-security</artifactId>
    <version>2.0.0.M4</version>
</dependency>
<dependency>
    <groupId>org.springframework.social</groupId>
    <artifactId>spring-social-core</artifactId>
    <version>2.0.0.M2</version>
</dependency>
<dependency>
    <groupId>org.springframework.social</groupId>
    <artifactId>spring-social-config</artifactId>
    <version>2.0.0.M2</version>
</dependency>

After that the user gets redirected to https://localhost:8443/signin/facebook . 之后,用户被重定向到https:// localhost:8443 / signin / facebook

I think there is another best way of doing so .As your angular webapp ( https://localhost:4200 ) comprises of webLayer so directly redirecting via form action is not a better way.You can use Proxy Routing click here 我认为还有另一种最好的方法。由于你的angular webapp( https:// localhost:4200 )包含webLayer所以直接通过表单动作重定向不是更好的方法。你可以使用代理路由 点击这里

Now in case of you are using you are using proxy routing u need to configure your proxy port (8443) by command. 现在,如果您正在使用代理路由,则需要按命令配置代理端口(8443)。

ng serve –proxy-config proxy.conf.json ng serve -proxy-config proxy.conf.json
where proxy.conf.json contain your configuration https://localhost:8443/ 其中proxy.conf.json包含您的配置https:// localhost:8443 /

then you need to first authenticate your each user/new user to your server(service layer) & then pass every request through user service layer controller .This will lead to pass every request through your server and it solve your problem. 然后,您需要首先向服务器(服务层)验证您的每个用户/新用户,然后通过用户服务层控制器传递每个请求。这将导致通过您的服务器传递每个请求,它将解决您的问题。

The user authorized my app, but my server does not know the user yet so do I 用户授权我的应用程序,但我的服务器不知道用户,所以我也是

This is my signup PoC code , FYI 这是我的signup PoC代码,仅供参考

@Controller
class HomeController : AbstractController() {

  private var sessionStrategy: SessionStrategy = HttpSessionSessionStrategy()

  @Inject
  private lateinit var connectionFactoryLocator: ConnectionFactoryLocator

  @Inject
  private lateinit var usersConnectionRepository: FoodUsersConnectionRepository

  @RequestMapping("/")
  fun index(): String {
    logger.info("index")
    return "index"
  }

  @RequestMapping("/signup")
  fun signup(nativeWebRequest: NativeWebRequest) : String {
    sessionStrategy.getAttribute(nativeWebRequest , ProviderSignInAttempt.SESSION_ATTRIBUTE)
      .takeIf { it != null }
      .also { it ->
        val attempt = it as ProviderSignInAttempt
        val connection = attempt.getConnection(connectionFactoryLocator)
        logger.info("conn.key = {}" , connection.key)
        val user = userDao.save(User(RandomStringUtils.randomAlphanumeric(8) , RandomStringUtils.randomAlphanumeric(8)))
        val connRepo: ConnectionRepository = usersConnectionRepository.createConnectionRepository(user.id.toString())
        connRepo.addConnection(connection)
      }
    return "signup"
  }

}

Points to notes : 注意事项:

I retrieve the connection object set in ProviderSignInController.handleSignIn() , it contains freshy (not mapped in db) providerId/providerUserId pair. 我检索在ProviderSignInController.handleSignIn()设置的连接对象,它包含freshy(未在db中映射)providerId / providerUserId对。 And I create a new local user , give it random username/password pair , and link the new providerId/providerUserId to the local user. 我创建一个新的本地用户,给它随机的用户名/密码对,并将新的providerId / providerUserId链接到本地​​用户。

This is a simple PoC code , it should be modified to conform to your business logic. 这是一个简单的PoC代码,应该修改它以符合您的业务逻辑。

Maybe you can display a form for user to fill-in his nickname or address or something. 也许你可以显示一个表格供用户填写他的昵称或地址或其他东西。 That's depend on your business logic. 这取决于您的业务逻辑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM