【问题标题】:Spring Security - Facebook春季安全 - Facebook
【发布时间】:2019-03-31 00:03:42
【问题描述】:

我想通过 facebook 登录我的网络应用程序。我有一个正常登录的表单,我想用 facebook 添加登录。我已通过链接 http://localhost:8080/ 将我的应用程序添加到开发人员 Facebook。我按照的例子 Using Spring Security 5 to integrate with OAuth 2-secured services such as Facebook and GitHub

我写了以下文件

SocialConfig.java

package pl.java.learning.todolist.infrastructure.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.web.context.annotation.RequestScope;
import pl.java.learning.todolist.infrastructure.social.Facebook;

@Configuration
public class SocialConfig {

    @Bean
    @RequestScope
    public Facebook facebook(OAuth2AuthorizedClientService clientService) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String accessToken = null;
        if (authentication.getClass().isAssignableFrom(OAuth2AuthenticationToken.class)) {
          OAuth2AuthenticationToken oauthToken = (OAuth2AuthenticationToken) authentication;
          String clientRegistrationId = oauthToken.getAuthorizedClientRegistrationId();
          if (clientRegistrationId.equals("facebook")) {
            OAuth2AuthorizedClient client = clientService.loadAuthorizedClient(clientRegistrationId, oauthToken.getName());
            accessToken = client.getAccessToken().getTokenValue();
          }
        }
        return new Facebook(accessToken);
    }
}

ApiBinding.java

package pl.java.learning.todolist.infrastructure.social;

import java.io.IOException;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.RestTemplate;

public abstract class ApiBinding {
  protected RestTemplate restTemplate;

  public ApiBinding(String accessToken) {
    this.restTemplate = new RestTemplate();
    if (accessToken != null) {
      this.restTemplate.getInterceptors().add(getBearerTokenInterceptor(accessToken));
    } else {
      this.restTemplate.getInterceptors().add(getNoTokenInterceptor());
    }
  }

  private ClientHttpRequestInterceptor getBearerTokenInterceptor(String accessToken) {
    return new ClientHttpRequestInterceptor() {
      @Override
      public ClientHttpResponse intercept(HttpRequest request, byte[] bytes, ClientHttpRequestExecution execution) throws IOException {
        request.getHeaders().add("Authorization", "Bearer " + accessToken);
        return execution.execute(request, bytes);
      }
    };
  }

  private ClientHttpRequestInterceptor getNoTokenInterceptor() {
    return new ClientHttpRequestInterceptor() {
      @Override
      public ClientHttpResponse intercept(HttpRequest request, byte[] bytes, ClientHttpRequestExecution execution) throws IOException {
        throw new IllegalStateException("Can't access the Facebook API without an access token");
      }
    };
  }
}

Facebook.java

package pl.java.learning.todolist.infrastructure.social;

public class Facebook extends ApiBinding {
  private static final String GRAPH_API_BASE_URL = "https://graph.facebook.com/v2.12";

  public Facebook(String accessToken) {
    super(accessToken);
  }

  public Profile getProfile() {
    return restTemplate.getForObject(GRAPH_API_BASE_URL + "/me", Profile.class);
  }

}

Profile.java

package pl.java.learning.todolist.infrastructure.social;

import lombok.Data;

@Data
public class Profile {
    private String id;
    private String name;
}

在 index.html 文件中,我添加了以下指向 facebook 的链接

    <a href="/oauth2/authorization/facebook"><img src="/image/facebook.png" class="imgsize img-fluid m-10 " margin="10px" alt=""></a>

文件 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>pl.java.learning</groupId>
    <artifactId>todo-list</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>todo-list</name>
    <description>To-do list project</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <swagger.version>2.9.2</swagger.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.flywaydb</groupId>
            <artifactId>flyway-core</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>${swagger.version}</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>${swagger.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <version>3.1.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>bootstrap</artifactId>
            <version>4.1.3</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>3.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity4</artifactId>
            <version>3.0.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2-client</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

但它不起作用并且没有重定向到 facebook,也许有人知道如何解决这个问题?

问候

【问题讨论】:

  • 嗨@Adrian,你能提供pom.xml吗?
  • 当然,我已经编辑了我的帖子
  • 我认为问题可能出在我的自定义 UserDetails 上的演员表上,因为当我单击按钮登录 facebook 并想查看一些内容时,我收到了类似 org.springframework.security.oauth2 的错误.core.user.DefaultOAuth2User 无法转换为 pl.java.learning.todolist.infrastructure.security.MyUserPrincipal
  • 那么看看pl.java.learning.todolist.infrastructure.security.MyUserPrincipal就好了:)
  • ok :) 我在下面添加了

标签: spring facebook security oauth-2.0


【解决方案1】:

我的用户主体

package pl.java.learning.todolist.infrastructure.security;

import java.util.Collection;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import pl.java.learning.todolist.domain.user.User;

@RequiredArgsConstructor
public class MyUserPrincipal implements UserDetails {

  private final User user;

  @Override
  public Collection<? extends GrantedAuthority> getAuthorities() {
    return user.getRoles();
  }

  public Long getUserId() {
    return user.getId();
  }

  @Override
  public String getPassword() {
    return user.getPassword();
  }

  @Override
  public String getUsername() {
    return user.getLogin();
  }

  @Override
  public boolean isAccountNonExpired() {
    return true;
  }

  @Override
  public boolean isAccountNonLocked() {
    return true;
  }

  @Override
  public boolean isCredentialsNonExpired() {
    return true;
  }

  @Override
  public boolean isEnabled() {
    return user.getEnabled();
  }
}

【讨论】:

  • 首先 - 您不需要将 User 存储为 MyUserPrincipal 类的属性。 MyUserPrincipal 和 User 是同一个实体。其次 - 您需要从 DefaultOAuth2User 扩展 MyUserPrincipal,所以它看起来像这样:public class MyUserPrincipal extends DefaultOAuth2User implements UserDetails
  • User 和 MyUserPrincipal 不一样。 MyUserPrincipal 帮助应用程序进行身份验证。用户实体保存在数据库中。
  • 或者我没有正确理解某些内容? :)
猜你喜欢
  • 2013-12-22
  • 2014-02-02
  • 2012-12-13
  • 2017-11-30
  • 2021-05-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多