OAuth2簡易實戰(四)-Github社交聯合登錄


1. OAuth2簡易實戰(四)-Github社交聯合登錄

1.1. 用到的第三方插件

https://github.com/spring-projects/spring-social-github

1.2. 測試步驟

1.2.1. 先在github上注冊一個OAuth Apps


我的配置內容如下

  1. 需要注意的,這里的最后一個回調地址的配置,格式嚴格規定,/connect/xxx,最后的github參數對應了特定頁面,后面我通過閱讀源碼來詳細解釋
  2. 注冊完之后,會有一個client id和client secret,這是需要配置到程序中的

1.2.2. 屬性配置

  1. applicaton.properties
spring.social.github.app-id=xxxx
spring.social.github.app-secret=xxxx
  1. 屬性類
@ConfigurationProperties(prefix = "spring.social.github")
public class GitHubProperties extends SocialProperties {

}

1.2.3. social核心配置

  1. 屬性配置導入,建立與github連接
@Configuration
@EnableSocial
@EnableConfigurationProperties(GitHubProperties.class)
public class GitHubConfiguration extends SocialAutoConfigurerAdapter {

	private final GitHubProperties properties;

	public GitHubConfiguration(GitHubProperties properties) {
		this.properties = properties;
	}

	@Bean
	@Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
	public GitHub gitHub(ConnectionRepository repository) {
		Connection<GitHub> connection = repository
				.findPrimaryConnection(GitHub.class);
		return connection != null ? connection.getApi() : null;
	}

	@Bean
	public ConnectController connectController(
			ConnectionFactoryLocator factoryLocator,
			ConnectionRepository repository) {

		ConnectController controller = new ConnectController(
			factoryLocator, repository);
		controller.setApplicationUrl("http://localhost:8080");
		return controller;
	}

	@Override
	protected ConnectionFactory<?> createConnectionFactory() {
		return new GitHubConnectionFactory(properties.getAppId(),
				properties.getAppSecret());
	}
}

1.2.4. controller層

@Controller
public class RepositoriesController {

	@Autowired
	private GitHub github;

	@Autowired
	private ConnectionRepository connectionRepository;

	@GetMapping
	public String repositories(Model model) {
		if (connectionRepository.findPrimaryConnection(GitHub.class) == null) {
			return "redirect:/connect/github";
		}

		String name = github.userOperations().getUserProfile().getUsername();
		String username = github.userOperations().getUserProfile()
				.getUsername();
		model.addAttribute("name", name);

		String uri = "https://api.github.com/users/{user}/repos";
		GitHubRepo[] repos = github.restOperations().getForObject(uri,
				GitHubRepo[].class, username);
		model.addAttribute("repositories", Arrays.asList(repos));

		return "repositories";
	}

}
  1. 當我們請求localhost:8080 會重定向到localhost:8080/connect/github ,這又是寫在哪呢?查看源代碼,會發現在social-web包的ConnectController類中有
@Controller
@RequestMapping({"/connect"})
public class ConnectController implements InitializingBean {
    @RequestMapping(
        value = {"/{providerId}"},
        method = {RequestMethod.GET}
    )
    public String connectionStatus(@PathVariable String providerId, NativeWebRequest request, Model model) {
        this.setNoCache(request);
        this.processFlash(request, model);
        List<Connection<?>> connections = this.connectionRepository.findConnections(providerId);
        this.setNoCache(request);
        if (connections.isEmpty()) {
            return this.connectView(providerId);
        } else {
            model.addAttribute("connections", connections);
            return this.connectedView(providerId);
        }
    }
  1. 進入connectView方法
    protected String connectView(String providerId) {
        return this.getViewPath() + providerId + "Connect";
    }
  1. 可以看到,在這里它固定拼接了參數Connect,所以,在自己的跳轉頁面中需要有特定的命名規范,這里一定就是githubConnect.html了
<html>
<head>
	<title>Social Authcode</title>
</head>
<body>
	<h2>Connect to GitHub to see your repositories</h2>

	<form action="/connect/github" method="POST">
		<input type="hidden" name="scope" value="public_repo user" />

		<div class="formInfo">
			Click the button to share your repositories with <b>social-github</b>
		</div>
		<p><button type="submit">Connect to GitHub</button></p>
	</form>

</body>
</html>
  1. 顯示頁面如下

  1. 點擊按鈕進行post請求,進入源碼如下
    @RequestMapping(
        value = {"/{providerId}"},
        method = {RequestMethod.POST}
    )
    public RedirectView connect(@PathVariable String providerId, NativeWebRequest request) {
        ConnectionFactory<?> connectionFactory = this.connectionFactoryLocator.getConnectionFactory(providerId);
        MultiValueMap<String, String> parameters = new LinkedMultiValueMap();
        this.preConnect(connectionFactory, parameters, request);

        try {
            return new RedirectView(this.connectSupport.buildOAuthUrl(connectionFactory, request, parameters));
        } catch (Exception var6) {
            this.sessionStrategy.setAttribute(request, "social_provider_error", var6);
            return this.connectionStatusRedirect(providerId, request);
        }
    }
  1. 層層深入后,會發現它本質還是在組裝授權參數,使用的是OAuth2的授權碼模式,最后組裝的http請求為如下,很明顯為了去獲得授權碼
https://github.com/login/oauth/authorize?client_id=9fc0081c3dd4f8b11f86&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fconnect%2Fgithub&scope=public_repo+user&state=e37f1891-cd45-47b4-adb4-5c541f777e60&state=48742b99-c04e-4dfd-af0a-f19b0193f1bb&state=c2737022-3cc7-4b80-92ce-fcba2ca9beb4
  1. 這最后跳轉這層的代碼如下,封裝成buildOAuthUrl方法進行了組裝
    public RedirectView connect(@PathVariable String providerId, NativeWebRequest request) {
        ConnectionFactory<?> connectionFactory = this.connectionFactoryLocator.getConnectionFactory(providerId);
        MultiValueMap<String, String> parameters = new LinkedMultiValueMap();
        this.preConnect(connectionFactory, parameters, request);

        try {
            return new RedirectView(this.connectSupport.buildOAuthUrl(connectionFactory, request, parameters));
        } catch (Exception var6) {
            this.sessionStrategy.setAttribute(request, "social_provider_error", var6);
            return this.connectionStatusRedirect(providerId, request);
        }
    }
  1. 獲取授權碼后,跳轉github登錄頁面


  2. 輸入用戶名密碼正確后立即回調到方法

    @RequestMapping(
        value = {"/{providerId}"},
        method = {RequestMethod.GET},
        params = {"code"}
    )
    public RedirectView oauth2Callback(@PathVariable String providerId, NativeWebRequest request) {
        try {
            OAuth2ConnectionFactory<?> connectionFactory = (OAuth2ConnectionFactory)this.connectionFactoryLocator.getConnectionFactory(providerId);
            Connection<?> connection = this.connectSupport.completeConnection(connectionFactory, request);
            this.addConnection(connection, connectionFactory, request);
        } catch (Exception var5) {
            this.sessionStrategy.setAttribute(request, "social_provider_error", var5);
            logger.warn("Exception while handling OAuth2 callback (" + var5.getMessage() + "). Redirecting to " + providerId + " connection status page.");
        }

        return this.connectionStatusRedirect(providerId, request);
    }
  1. 通過授權碼再去取得token

  1. 再繼續跳轉/connect/github
 @RequestMapping(
        value = {"/{providerId}"},
        method = {RequestMethod.GET}
    )
    public String connectionStatus(@PathVariable String providerId, NativeWebRequest request, Model model) {
        this.setNoCache(request);
        this.processFlash(request, model);
        List<Connection<?>> connections = this.connectionRepository.findConnections(providerId);
        this.setNoCache(request);
        if (connections.isEmpty()) {
            return this.connectView(providerId);
        } else {
            model.addAttribute("connections", connections);
            return this.connectedView(providerId);
        }
    }
  1. 此時connections有值,進入connectedView方法
    protected String connectedView(String providerId) {
        return this.getViewPath() + providerId + "Connected";
    }
  1. 由此可以知道,下個頁面我們命名也定下來了,githubConnected.html,這里簡單一個點擊連接,跳轉到主頁
<html>
	<head>
		<title>Social Authcode</title>
	</head>
	<body>
		<h2>Connected to GitHub</h2>

		<p>
			Click <a href="/">here</a> to see your repositories.
		</p>
	</body>
</html>

  1. 到此其實授權操作都已經完成了,接下來就是正式調用github需要權限的接口了,點擊here

代碼學習地址 https://github.com/spring2go/oauth2lab


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM