Spring Security OAuth2 与Spring Boot的结合的第三方登录认证授权机制

 

大家做第三方登录的客户端开发大多都是按照官网的文档来开发,没有走OAuth2 client的机制,其实这样的弊端很明显,官网提供的第三方登录的文档都是js调用,那就会过分暴露用户的资料,如果是一个前台项目(商城前台,游戏前台等等)还可以原谅,但是如果是一个后台管理的项目,那就很危险了。

我司是对技术要求极其严格的公司,肯定不允许这样不安全的开发存在。故我是用的Spirng Security OAuth2来实现了第三方的接入,我实现了facebook,google,github的第三方登录。而且还进行了授权。

 我简单描述一下OAuth2的机制:OAuth协议被广泛应用于第三方授权登录中,用户可以通过第三方登录来使用该网站,能免去用户注册的麻烦,用户体验更佳。OAuth2定义了五种角色。客户端(Client)用户代理(User Agent)资源所有者(Resource Owner)授权服务器(Authorization Server)资源服务器(Resource Server)。OAuth协议已定义了4种授权模式,其中最具代表性的就是授权码模式,Spring Security OAuth2就是参用的这种模式。

整个授权流程说明如下(具体参数释义见下文):

  1. 客户端携带client_id, scope, redirect_uri, state等信息引导用户请求授权服务器的授权端点下发code

  2. 授权服务器验证客户端身份,验证通过则询问用户是否同意授权(此时会跳转到用户能够直观看到的授权页面,等待用户点击确认授权)

  3. 假设用户同意授权,此时授权服务器会将code和state(如果客户端传递了该参数)拼接在redirect_uri后面,以302形式下发code

  4. 客户端携带code, redirect_uri, 以及client_secret请求授权服务器的令牌端点下发access_token(这一步实际上中间经过了客户端的服务器,除了code,其它参数都是在应用服务器端添加,下文会细讲)

  5. 授权服务器验证客户端身份,同时验证code,以及redirect_uri是否与请求code时相同,验证通过后下发access_token,并选择性下发refresh_token

 

请求参数说明:

名称是否必须描述信息
response_type必须对于授权码模式response_type=code
client_id必须客户端ID,用于标识一个客户端,等同于appId,在注册应用时生成
redirect_uri可选授权回调地址,具体参见2.2.3小节
scope可选权限范围,用于对客户端的权限进行控制,如果客户端没有传递该参数,那么服务器则以该应用的所有权限代替
state推荐用于维持请求和回调过程中的状态,防止CSRF攻击,服务器不对该参数做任何处理,如果客户端携带了该参数,则服务器在响应时原封不动的返回

 

对于OAuth协议不太熟悉的朋友,可以查看该位仁兄的文章:http://www.zhenchao.org/2017/03/04/oauth-v2-principle/

OAuth2.0协议的书籍:https://tools.ietf.org/html/rfc6749

大家搞明白了原理,接下来就是使用Spring Security OAuth2(后面会发现,Spring Security OAuth2是通过filer机制来解决OAuth协议认证授权的)来解决企业问题:

我的项目是maven项目使用的Spring Boot项目,首先是jar包依赖:    

        <dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>
        <dependency>
			<groupId>org.springframework.security.oauth</groupId>
			<artifactId>spring-security-oauth2</artifactId>
		</dependency>

然后是官网资源的配置这一步比较简单:在官网进行项目的配置 下面是官网的链接(请先注册登录https://github.com/

https://github.com/settings/applications/new

注:github支持http://localhost:8080的站点

然后是java config配置:

HttpSecurity类:进行权限的配置,具体哪里路径可以直接放行.antMatchers(…).permitAll()
哪些路径需要权限认证 .antMatchers(…).hasAutority(…) 仅测试需要
.anyRequest().authenticated()
配置登录页面,登录错误页面 以及安全退出,安全退出页面,记住我等等。

ClientResources:资源所有者

          包括:AuthorizationCodeResourceDetails有GrantType(授权机制"authorization_code"),preEstablishedRedirectUri,userAuthorizationUri,clientd,clientSecret,scope,authorizationScheme,tokenName等属性。

                                            ResourceServerProperties:Configuration properties for OAuth2 Resources.及:从配置文件获取信息的bean对象 资源 。包含:clientId clientSecret userInfoUri tokenInfoUri属性。

OAuth2ClientContextFilter:OAuth2客户端的安全认证过滤器 所有请求的路径uri校验

UserInfoTokenServices:需要自定义实现,提供用户信息REST服务,默认的实现不能进行授权处理,

需要重写loadAuthentication方法,从数据库加载用户权限信息,如果不重写该方法,所有的通过第三方登录的用户都将只有ROLE_USER的权限,显然不能满足企业需要。

下面是所有的java config的配置信息。

ps:这可是我一点点总结的配置,望大家珍惜。

@EnableOAuth2Client
@EnableAuthorizationServer
@Order(6)
public class SocialApplication extends WebSecurityConfigurerAdapter {

@Override
	protected void configure(HttpSecurity http) throws Exception {
		// @formatter:off
		http.antMatcher("/**").authorizeRequests().antMatchers("/", "/login**", "/webjars/**","/js/**","/css/**","/hello").permitAll()
				.antMatchers("/hello").hasAuthority("ROLE_USER")
				.anyRequest().authenticated().and().exceptionHandling()
				.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/")).and().logout()
				.logoutSuccessUrl("/").permitAll().and()
				.addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
		// @formatter:on
	}

	@Bean
	@ConfigurationProperties("github")
	public ClientResources github() {
		return new ClientResources();
	}
private Filter ssoFilter() {
		CompositeFilter filter = new CompositeFilter();
		List<Filter> filters = new ArrayList<>();
		filters.add(ssoFilter(github(), "/login/github"));
		filter.setFilters(filters);
		return filter;
	}

	private Filter ssoFilter(ClientResources client, String path) {
		OAuth2ClientAuthenticationProcessingFilter oAuth2ClientAuthenticationFilter = new OAuth2ClientAuthenticationProcessingFilter(path);
		OAuth2RestTemplate oAuth2RestTemplate = new OAuth2RestTemplate(client.getClient(), oauth2ClientContext);
		oAuth2ClientAuthenticationFilter.setRestTemplate(oAuth2RestTemplate);
		UserInfoTokenServices tokenServices = new UserInfoTokenServices(client.getResource().getUserInfoUri(),
				client.getClient().getClientId());
		tokenServices.setRestTemplate(oAuth2RestTemplate);
		oAuth2ClientAuthenticationFilter.setTokenServices(tokenServices);
		return oAuth2ClientAuthenticationFilter;
	}

}

class ClientResources {

	@NestedConfigurationProperty
	private AuthorizationCodeResourceDetails client = new AuthorizationCodeResourceDetails();

	@NestedConfigurationProperty
	private ResourceServerProperties resource = new ResourceServerProperties();

	public AuthorizationCodeResourceDetails getClient() {
		return client;
	}

	public ResourceServerProperties getResource() {
		return resource;
	}
}

 

做完了java config的配置,还需要配置application.yml文件,

github:
  client:
    clientId: bd1c0a783ccdd1c9b9e4
    clientSecret: 1a9030fbca47a5b2c28e92f19050bb77824b5ad1
    accessTokenUri: https://github.com/login/oauth/access_token
    userAuthorizationUri: https://github.com/login/oauth/authorize
    clientAuthenticationScheme: form
  resource:
    userInfoUri: https://api.github.com/user

 

接下来就是官网图标的渲染,我是从官网扒下来的html

<!--  Github按钮 -->
		<div>
		<a href="/login/github">
		<svg aria-hidden="true" class="octicon octicon-mark-github"
			height="32" version="1.1" viewBox="0 0 16 16" width="32">
			<path fill-rule="evenodd"
				d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z">
				</path></svg>
		</a>
		</div>

 

到这里就大功告成了,大家可以启动自己的项目爽一把了。哈哈,我第一次看到github的第三方登录页面的时候超级开心,哈哈,大家也会和我一样很开心的。相同的机制,我也做了facebook,google的第三方登录很容易的。有哪里不太明白的地方可以留言,随时可以回答各位。

如果大家对Spring Security感兴趣,可以查看我的博客:

http://blog.csdn.net/weixin_38024391/article/details/71404582

 

 

 

 

 

 

转载于:https://my.oschina.net/u/3375419/blog/895728

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值