У меня есть веб-сайт (приложение Angular), доступ к которому я могу получить на https: // локальный: 4200, и сервер (чистый REST API), который находится на https: // локальный: 8443.
Поскольку конечные точки REST защищены, пользователь должен войти на мой сервер. Очевидно, я хочу, чтобы пользователи могли регистрироваться с помощью Facebook и продолжать общаться с моим сервером после входа в систему.
Согласно документы
POST /signin/{providerId}- Initiates the sign in flow.
вот почему есть кнопка, которая делает именно это:
<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>
Оттуда какое-то время все работает нормально. Пользователь перенаправляется на страницу авторизации Facebook, где нажимается кнопка авторизации. После этого пользователь перенаправляется на https: // localhost: 8443 / signin / facebook.
Похоже, что по умолчанию, если пользователь неизвестен, будет другое перенаправление на https: // localhost: 8443 / регистрация (см. документы)
If the provider user ID matches more than one existing connection,
ProviderSignInControllerwill 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. 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. The default sign in URL is "/signin" (relative to the application root), but can be customized by setting thesignInUrlproperty.
На моем сервере это выглядит так (заимствовано из образца приложения):
@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();
}
}
И вот мои проблемы:
Прежде всего мне нужно знать, что я должен делать в этой конечной точке. Пользователь авторизовал мое приложение, но мой сервер еще не знает пользователя, поэтому я
connection.fetchUserProfile() и сохраните нового пользователя в моей базе данныхВо-вторых, я не знаю, как я должен перенаправить отсюда обратно на свой веб-сайт, который, как объяснялось, находится на https: // локальный: 4200. Но, конечно, мой сервер этого не знает.
Есть ли шанс, что кто-нибудь сможет помочь мне в этом?
Это 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, связанные с Spring Social:
<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>
@TarunLalwani Хм, нет, это другая установка, и я думаю, что проблема также отличается от того, что у меня есть. Я знаю, почему происходят перенаправления - я не знаю, как перенаправить обратно на веб-клиент, который размещается где-то еще.
After that the user gets redirected to https://localhost:8443/signin/facebook.
Я думаю, что есть еще один лучший способ сделать это. Поскольку ваше угловое веб-приложение (https: // локальный: 4200) состоит из веб-слоя, поэтому прямое перенаправление через действие формы не лучший способ. Вы можете использовать Прокси-маршрутизациякликните сюда
Теперь, если вы используете прокси-маршрутизацию, вам необходимо настроить порт прокси (8443) с помощью команды.
ng serve –proxy-config proxy.conf.json
where proxy.conf.json contain your configuration https://localhost:8443/
тогда вам нужно сначала аутентифицировать каждого пользователя / нового пользователя на вашем сервере (уровень обслуживания), а затем передавать каждый запрос через контроллер уровня обслуживания пользователя. Это приведет к передаче каждого запроса через ваш сервер и решит вашу проблему.
The user authorized my app, but my server does not know the user yet so do I
Простите, я не понимаю. локальный: 8443 / вход / facebook - это мое перенаправление OAuth с Facebook на мой сервер. Я не уверен, как здесь может помочь прокси-маршрутизация. В любом случае все запросы уже проходят через мой сервер.
Пользователь авторизовал мое приложение. Как работает ваша авторизация? Если вы нажимаете свой запрос oauth локальный: 8443 / вход / facebook .. после авторизации он возвращается на сервер. Где роль вашего углового веб-приложения? Разве не требуется авторизовать соединение между сетью а сервисный слой? Я только хочу знать, что такое промежуточный уровень вашего веб-приложения и сервисов angular.
Вы сами использовали Spring Social в одном из своих проектов?
Дело в том, что я не вижу, что эта прокси-конфигурация делает для меня, за исключением экстернализации URL-адреса моего REST API - может быть, я здесь что-то не так? Однако, как указано в моем вопросе, я отправляю POST в https://localhost:8443/signin/facebook, который запускает магию Spring Social. Пользователь перенаправляется на страницу Facebook и авторизует мое приложение. Затем я получаю обратный вызов от Facebook и каким-то образом попадаю на https://localhost:8443/signup в моем браузере. Я либо делаю что-то совершенно не так, либо мне нужно что-то адаптировать из-за того, что веб-клиент и ..
.. REST API находится в двух разных доменах. Эта «прокси-маршрутизация» больше похожа на причудливое название для экстернализации / централизации URL-адресов других конечных веб-точек?
Это мой код PoC для signup, к вашему сведению
@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"
}
}
Указывает на примечания:
Я получаю объект подключения, установленный в ProviderSignInController.handleSignIn(), он содержит свежую (не отображенную в db) пару providerId / providerUserId.
И я создаю нового локального пользователя, даю ему случайную пару имени пользователя и пароля и связываю новый providerId / providerUserId с локальным пользователем.
Это простой PoC-код, его следует изменить в соответствии с вашей бизнес-логикой.
Может быть, вы можете отобразить форму, в которой пользователь сможет ввести свой ник, адрес или что-то в этом роде. Это зависит от вашей бизнес-логики.
Посмотрите, поможет ли учебник в этом вопросе SO stackoverflow.com/questions/49942640/…?