spring security oauth2.0 client集成第三方登录

   大家上网的时候可能会遇见这样的一个问题,就是我们去访问一个网站,但是又不想去注册这个网站的账号,账号太多了实在是记不来,于是我们可以用qq或者微信登录这个网站,简直不要太方便有没有。
   这么神奇的事情怎么能不去一探究竟呢,今天我们就来给他说道说道。
   其实那些第三方服务他们都是使用了Oauth2.0这个协议,做的事情都是差不多,只是细节不同而已。

什么是 OAuth 2.0?

   OAuth 是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。目前,OAuth 的最新版本为 2.0
   OAuth 允许用户提供一个令牌,而不是用户名和密码来访问他们存放在特定服务提供者的数据。每一个令牌授权一个特定的网站(例如,视频编辑网站)在特定的时段(例如,接下来的2小时内)内访问特定的资源(例如仅仅是某一相册中的视频)。这样,OAuth 允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要分享他们的访问许可或他们数据的所有内容

OAuth 2.0 主要有4类角色

  • resource owner:资源所有者,指终端的“用户”(user)
  • resource server:资源服务器,即服务提供商存放受保护资源。访问这些资源,需要获得访问令牌(access token)。它与认证服务器,可以是同一台服务器,也可以是不同的服务器。如果,我们访问新浪博客网站,那么如果使用新浪博客的账号来登录新浪博客网站,那么新浪博客的资源和新浪博客的认证都是同一家,可以认为是同一个服务器。如果,我们是新浪博客账号去登录了知乎,那么显然知乎的资源和新浪的认证不是一个服务器。
  • client:客户端,代表向受保护资源进行资源请求的第三方应用程序。
  • authorization server: 授权服务器, 在验证资源所有者并获得授权成功后,将发放访问令牌给客户端

OAuth2.0的四种认证模式

OAuth 2.0定义了四种授权方式。

  • 授权码模式(authorization code)
  • 简化模式(implicit)(client为浏览器/前端应用)
  • 密码模式(resource owner password credentials)(用户密码暴露给client端不安全)
  • 客户端模式(client credentials)(主要用于api认证,跟用户无关)
    这里facebook、Twitter、github、google均支持第一种模式,也是最安全的模式。

OAuth 2.0认证流程

这里主要讲的是授权码模式,见下图
授权码模式认证流程
上图中所涉及到的对象分别为:

  • Client 第三方应用,我们的应用就是一个Client
  • Resource Owner 资源所有者,即用户
  • Authorization Server 授权服务器,即提供第三方登录服务的服务器,如Github
  • Resource Server 拥有资源信息的服务器,通常和授权服务器属于同一应用

根据上图的信息,我们可以知道OAuth2的基本流程为:

  • 用户点击客户端提供的授权请求
  • 客户端请求服务的授权页面呈现给用户,用户点击确认授权后服务端返回授权许可凭证给客户端
  • 客户端应用通过第二步的凭证(code)向授权服务器请求授权
  • 授权服务器验证凭证(code)通过后,同意授权,并返回一个资源访问的凭证(Access Token)。
  • 客户端应用通过第四步的凭证(Access Token)向资源服务器请求相关资源。
  • 资源服务器验证凭证(Access Token)通过后,将客户端应用请求的资源返回。

Start doing now

github配置

   好,我们了解了OAuth2.0之后,接下来介绍在spring boot2.0+security5环境下怎么实现Oauth2.0客户端第三方登录,这里我使用了github,其实qq,微信,微博那些都一样,都是基于OAuth2.0协议,只是国内这些还需要域名备案号这些信息罢了。
   首先去github注册开发者应用,点击settings> Developer settings>OAuth app>new Oauth App,会看到下面的页面
在这里插入图片描述

  • Application name    这个是你创建的应用名称,可以随便填
  • Homepage URL     这个是用户使用github登陆成功后跳转的页面
  • Applocation description 这个是你应用的描述,可以随便填
  • Authorization callback URL  这个是你的应用向github服务端请求node的回调地址,需要配置拦截器拦截此URL获取ccode.

依赖

        <dependency>
			<groupId>org.springframework.security.oauth.boot</groupId>
			<artifactId>spring-security-oauth2-autoconfigure</artifactId>
			<version>2.0.0.RELEASE</version>
		</dependency>

配置

#github新建app得到的id 和secret,这个需要填你自己配置的
github.client.clientId=a65cbf9654dfeb0d5142
github.client.clientSecret=5dd7327a494c4bea46b488a052fc1012dfbcc794
#获取token的地址
github.client.accessTokenUri=https://github.com/login/oauth/access_token
#登陆之后询问的地址
github.client.userAuthorizationUri=https://github.com/login/oauth/authorize
#2个Schema是指请求参数以什么样的方式跟随
github.client.authenticationScheme=query
github.client.clientAuthenticationScheme=form
#请求用户信息的url
github.client.resource.userInfoUri=https://api.github.com/user

security配置类

安全配置上需要加上@EnableWebSecurity 、 @EnableOAuth2Client注解,来启用Web security Oauth2 客户端,表明这是一个OAuth 2.0 客户端

@EnableWebSecurity
@EnableOAuth2Client  // 启用 OAuth 2.0 客户端 
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    //注入Oauth2.0客户端上下文
    @Autowired
	OAuth2ClientContext oauth2ClientContext;

注册两个bean获取配置文件自定义的内容,并返回相应的类

 @Bean
	  @ConfigurationProperties("github.client")
	  public AuthorizationCodeResourceDetails github() {
	    return new AuthorizationCodeResourceDetails();
	  }
	  
	  @Bean
	  @ConfigurationProperties("github.resource")
	  public ResourceServerProperties githubResource() {
	    return new ResourceServerProperties();
	  }

注册一个过滤器,用来截取code的回调地址,获取token

//自定义过滤器,用于拦截oauth2第三方登录返回code的url,并根据code,clientid,clientSecret去授权服务器拿accace_token
	private Filter ssoFilter() {
		  //OAuth2ClientAuthenticationProcessingFilter
		  //它的构造器需要传入defaultFilterProcessesUrl,用于指定这个filter拦截哪个url。
		  //它依赖OAuth2RestTemplate来获取token
		  //还依赖ResourceServerTokenServices进行校验token
		  OAuth2ClientAuthenticationProcessingFilter githubFilter = new OAuth2ClientAuthenticationProcessingFilter("/login/github");
		  //对rest template的封装,为获取token等提供便捷方法
		  //DefaultUserInfoRestTemplateFactory实例了OAuth2RestTemplate,这个提供了OAuth2RestTemplate
		  OAuth2RestTemplate githubTemplate = new OAuth2RestTemplate(github(), oauth2ClientContext);
		  githubFilter.setRestTemplate(githubTemplate);
		  UserInfoTokenServices tokenServices = new UserInfoTokenServices(githubResource().getUserInfoUri(), github().getClientId());
		  tokenServices.setRestTemplate(githubTemplate);
		  githubFilter.setTokenServices(tokenServices);
		  return githubFilter;
		}

注意这里的/login/github对应与在github填的Authorization callback URL。页面上使用github登录的链接也要写这个,security会帮我们做好一切流程

接下来需要注册我们的过滤器

 /*注册一个额外的Filter:OAuth2ClientContextFilter
	   * 主要作用是重定向,当遇到需要权限的页面或URL,代码抛出异常,这时这个Filter将重定向到OAuth鉴权的地址
	   */
	  @Bean
		public FilterRegistrationBean<OAuth2ClientContextFilter> oauth2ClientFilterRegistration(OAuth2ClientContextFilter filter) {
			FilterRegistrationBean<OAuth2ClientContextFilter> registration = new FilterRegistrationBean<OAuth2ClientContextFilter>();
			registration.setFilter(filter);
			registration.setOrder(-100);
			return registration;
		}

最后还有至关重要的一步,把自定义的过滤器添加到过滤器链中基本过滤器的前面

//在网站基本认证之前添加ssoFilter过滤器
		http.addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);

如此这般,所有的工作就完成了
打开项目,点击页面上使用github登录的链接在这里插入图片描述
点击授权之后
在这里插入图片描述
   可以看到github的服务器给我们颁发了code,然后将页面重定向到我们配置的Homepage URL ,至此整个Oauth2.0的认证流程结束。
   这里只要配置客户端,@EnableOAuth2Client就可以支持所有的社交平台,关键有一点,如果用户时第一次登陆,需要将用户信息注册到我们自己的数据库中,与数据库中的用户一一映射,就可以判断当前登陆的用户是对应我们数据库自己的平台身份。并且,Oauth2登陆时,我们将自定义的用户身份(也就是社交平台对应自己数据库的User)返回给security,进行登陆。这样就进行了用户绑定。这里主要实现了自定义的PrincipalExtractor接口,并非使用默认实现FixedPrincipalExtractor。参考这篇文章

源码

这里就不贴我的代码了,放一下官网的demo,其实也一样

官方demo源码

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
您好,关于在 Spring Security OAuth2.0 客户端动态跳过认证,可以使用自定义过滤器来实现,具体实现如下: 1.自定义过滤器: ```java public class SkipTokenFilter extends OncePerRequestFilter { private AntPathMatcher antPathMatcher = new AntPathMatcher(); @Autowired private OAuth2AuthorizedClientService authorizedClientService; @Autowired private OAuth2AuthorizedClientRepository authorizedClientRepository; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String requestURI = request.getRequestURI(); String clientRegistrationId = "your-client-registration-id"; // 客户端注册ID if (!antPathMatcher.match("/oauth2/**", requestURI) && !antPathMatcher.match("/error", requestURI)) { OAuth2AuthorizedClient authorizedClient = authorizedClientService.loadAuthorizedClient(clientRegistrationId, getAuthentication(request), request); if (authorizedClient == null) { // 跳过认证 HttpSession session = request.getSession(false); if (session != null) { session.setAttribute(OAuth2AuthorizationContext.class.getName(), new OAuth2AuthorizationContext(null, null, clientRegistrationId)); } filterChain.doFilter(request, response); return; } request.setAttribute(OAuth2AuthorizationContext.class.getName(), new OAuth2AuthorizationContext(authorizedClient.getAccessToken(), null, clientRegistrationId)); } filterChain.doFilter(request, response); } private Authentication getAuthentication(HttpServletRequest request) { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication == null) { String authorization = request.getHeader(HttpHeaders.AUTHORIZATION); if (StringUtils.isNotEmpty(authorization)) { int index = authorization.indexOf(' '); if (index > 0) { String type = authorization.substring(0, index); if ("Bearer".equalsIgnoreCase(type)) { String token = authorization.substring(index + 1); authentication = new BearerTokenAuthentication(new BearerTokenAuthenticationToken(token)); } } } } return authentication; } } ``` 2.在 Spring Security 配置中添加自定义过滤器: ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { // ... http.addFilterBefore(new SkipTokenFilter(), OAuth2AuthorizationRequestRedirectFilter.class); } } ``` 以上就是通过自定义过滤器在 Spring Security OAuth2.0 客户端动态跳过认证的实现方法,希望能对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值