SpringSecurity学习总结-4 第五章 使用Spring Social开发第三方登录

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Golang全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注go)
img

正文

@Override
public boolean test(QQ qq) {
return true;
}

/**

  • 数据适配:将QQ接口获取到的数据转换成Connection里标准数据
  • @param qq
  • @param connectionValues
    */
    @Override
    public void setConnectionValues(QQ qq, ConnectionValues connectionValues) {
    QQUserInfo userInfo = qq.getUserInfo();

connectionValues.setDisplayName(userInfo.getNickname());
connectionValues.setImageUrl(userInfo.getFigureurl_qq_1());
//个人主页:QQ是没有个人主页的,设为null
connectionValues.setProfileUrl(null);
connectionValues.setProviderUserId(userInfo.getOpenId());
}

/**

  • 获取用户主页信息,暂时用不到
  • @param qq
  • @return
    */
    @Override
    public UserProfile fetchUserProfile(QQ qq) {
    return null;
    }

/**

  • 更新QQ信息(用不到,QQ无此功能)
  • @param qq
  • @param s
    */
    @Override
    public void updateStatus(QQ qq, String s) {

}
}

3.3 新建ConnectionFacotory并继承OAuth2Connection

package security.core.social.qq.connect;

import org.springframework.social.connect.support.OAuth2ConnectionFactory;
import security.core.social.qq.api.QQ;

/**

  • QQConnectionFactory继承OAuth2ConnectionFactory的泛型是要适配的接口,作用是用来生成Connection
    */
    public class QQConnectionFactory extends OAuth2ConnectionFactory {

/**

  • QQConnectionFactory的构造函数
  • @param providerId
  • @param appId
  • @param appScret
    /
    public QQConnectionFactory(String providerId,String appId,String appScret) {
    /
    *
  • providerId:服务提供商的唯一标识
  • serviceProvider:QQServiceProvider
  • apiAdapter:QQAdapter
    */
    super(providerId, new QQServiceProvider(appId,appScret), new QQAdapter());
    }
    }

3.4 新建一个配置类SocialConfig,使用springsocial的配置将从第三方获取到的用户数据存储到数据库中

package security.core.social;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.encrypt.Encryptors;
import org.springframework.social.config.annotation.EnableSocial;
import org.springframework.social.config.annotation.SocialConfigurerAdapter;
import org.springframework.social.connect.ConnectionFactoryLocator;
import org.springframework.social.connect.UsersConnectionRepository;
import org.springframework.social.connect.jdbc.JdbcUsersConnectionRepository;

import javax.sql.DataSource;

/**

  • SocialConfig:用于将从第三方获取到的用户数据存储到数据库中
  • EnableSocial:将项目的social特性开启起来
    */
    @Configuration
    @EnableSocial
    public class SocialConfig extends SocialConfigurerAdapter {

@Autowired
private DataSource dataSource;

/**

  • JdbcUsersConnectionRepository构造函数的三个参数的作用:
  • dataSource:用于连接数据库
  • connectionFactoryLocator:用于查找具体使用的ConnectionFactoryLocator
  • textEncryptor:用于加解密数据
  • @param connectionFactoryLocator
  • @return
    */
    @Override
    public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
    //Encryptors.noOpText():是不做任何加解密
    return new JdbcUsersConnectionRepository(dataSource,connectionFactoryLocator, Encryptors.noOpText());
    }
    }

3.5 将 JdbcUsersConnectionRepository使用的数据表的建表语句拿到数据库里执行建表,建表语句在JdbcUsersConnectionRepository类的旁边

3.6给新建的数据表加入前缀

/**

  • JdbcUsersConnectionRepository构造函数的三个参数的作用:
  • dataSource:用于连接数据库
  • connectionFactoryLocator:用于查找具体使用的ConnectionFactoryLocator
  • textEncryptor:用于加解密数据
  • @param connectionFactoryLocator
  • @return
    */
    @Override
    public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
    //Encryptors.noOpText():是不做任何加解密
    JdbcUsersConnectionRepository repository = new JdbcUsersConnectionRepository(dataSource,connectionFactoryLocator, Encryptors.noOpText());
    //setTablePrefix:设置表的前缀
    repository.setTablePrefix(“u_”);
    return repository;
    }

完整代码:

package security.core.social;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.encrypt.Encryptors;
import org.springframework.social.config.annotation.EnableSocial;
import org.springframework.social.config.annotation.SocialConfigurerAdapter;
import org.springframework.social.connect.ConnectionFactoryLocator;
import org.springframework.social.connect.UsersConnectionRepository;
import org.springframework.social.connect.jdbc.JdbcUsersConnectionRepository;

import javax.sql.DataSource;

/**

  • SocialConfig:用于将从第三方获取到的用户数据存储到数据库中
  • EnableSocial:将项目的social特性开启起来
    */
    @Configuration
    @EnableSocial
    public class SocialConfig extends SocialConfigurerAdapter {

@Autowired
private DataSource dataSource;

/**

  • JdbcUsersConnectionRepository构造函数的三个参数的作用:
  • dataSource:用于连接数据库
  • connectionFactoryLocator:用于查找具体使用的ConnectionFactoryLocator
  • textEncryptor:用于加解密数据
  • @param connectionFactoryLocator
  • @return
    */
    @Override
    public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
    //Encryptors.noOpText():是不做任何加解密
    JdbcUsersConnectionRepository repository = new JdbcUsersConnectionRepository(dataSource,connectionFactoryLocator, Encryptors.noOpText());
    //setTablePrefix:设置表的前缀
    repository.setTablePrefix(“u_”);
    return repository;
    }
    }

3.7 使用 userId获取用户信息

修改MyUserDetailsService,加入实现SocialUserDetailsService,用于通过userId来获取用户信息

package security.browser.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.social.security.SocialUser;
import org.springframework.social.security.SocialUserDetails;
import org.springframework.social.security.SocialUserDetailsService;
import org.springframework.stereotype.Component;

/**

  • SocialUserDetailsService:是social的获取用户信息的接口类
    */
    @Component
    @Slf4j
    public class MyUserDetailsService implements UserDetailsService, SocialUserDetailsService {

@Autowired
private PasswordEncoder myPasswordEncoder;
/**

  • 可以@AutowiredDao层接口从而实现根据用户名去查找用户信息
  • @param username
  • @return
  • @throws UsernameNotFoundException
    */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    log.info("用户名: "+username);

String password = myPasswordEncoder.encode(“123456”);
log.info(“密码:”+password);

//这个User类实现了UserDetails
//密码应该是数据库查询出的密码
//authorities:用户权限的集合,即用来给用户授权
User user = new User(username,password, AuthorityUtils.commaSeparatedStringToAuthorityList(“admin”));

return user;
}

/**

  • 通过userId获取用户信息
  • @param userId
  • @return
  • @throws UsernameNotFoundException
    */
    @Override
    public SocialUserDetails loadUserByUserId(String userId) throws UsernameNotFoundException {
    log.info("用户Id: "+userId);

String password = myPasswordEncoder.encode(“123456”);
log.info(“密码:”+password);

//这个User类实现了UserDetails
//密码应该是数据库查询出的密码
//authorities:用户权限的集合,即用来给用户授权
return new SocialUser(userId,password, AuthorityUtils.commaSeparatedStringToAuthorityList(“admin”));
}
}

3.8新建QQProperties的相关配置类

package security.core.properties;

/**

  • QQ登录的相关配置
    */
    public class QQProperties{

/**

  • 从服务提供商处申请的本项目的appId
    */
    private String appId;

/**

  • 从服务提供商处申请的本项目的appSecret
    */
    private String appSecret;

/**

  • 服务提供商的标识
    */
    private String provideId = “qq”;

public String getAppId() {
return appId;
}

public void setAppId(String appId) {
this.appId = appId;
}

public String getAppSecret() {
return appSecret;
}

public void setAppSecret(String appSecret) {
this.appSecret = appSecret;
}

public String getProvideId() {
return provideId;
}

public void setProvideId(String provideId) {
this.provideId = provideId;
}
}

3.9 新建SocialProperties相关的配置类

package security.core.properties;

/**

  • 社交相关的配置类
    */
    public class SocialProperties {

private QQProperties qq = new QQProperties();

public QQProperties getQqProperties() {
return qq;
}

public void setQqProperties(QQProperties qq) {
this.qq = qq;
}
}

3.10 在SecurityProperties中加入SocialProperties配置

/**

  • 社交相关的配置
    */
    private SocialProperties social = new SocialProperties();

public SocialProperties getSocial() {
return social;
}

public void setSocial(SocialProperties social) {
this.social = social;
}

完整代码:

package security.core.properties;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

@Component
@PropertySource(“classpath:application-browser.properties”)
//@PropertySource(value= {“classpath:application-demo.properties”,“classpath:application-browser.properties”})
@ConfigurationProperties(“imooc.security”)
public class SecurityProperties {

/**

  • 浏览器相关的配置
    */
    private BrowserProperties browser = new BrowserProperties();

/**

  • 验证码相关的配置
    */
    private ValidateCodeProperties code = new ValidateCodeProperties();

/**

  • 社交相关的配置
    */
    private SocialProperties social = new SocialProperties();

public BrowserProperties getBrowser() {
return browser;
}

public void setBrowser(BrowserProperties browser) {
this.browser = browser;
}

public ValidateCodeProperties getCode() {
return code;
}

public void setCode(ValidateCodeProperties code) {
this.code = code;
}

public SocialProperties getSocial() {
return social;
}

public void setSocial(SocialProperties social) {
this.social = social;
}
}

3.11 新建SocialAutoConfigurerAdapter,因为使用的SpringSocial中没有SocialAutoConfigurerAdapter,所以新建一个

package security.core.social.qq.config;

import org.springframework.core.env.Environment;
import org.springframework.social.config.annotation.ConnectionFactoryConfigurer;
import org.springframework.social.config.annotation.SocialConfigurerAdapter;
import org.springframework.social.connect.ConnectionFactory;

/**

  • 因为使用的SpringSocial中没有SocialAutoConfigurerAdapter,所以新建一个
    */
    public abstract class SocialAutoConfigurerAdapter extends SocialConfigurerAdapter {
    public SocialAutoConfigurerAdapter() {
    }
    public void addConnectionFactories(ConnectionFactoryConfigurer configurer, Environment environment) {
    configurer.addConnectionFactory(this.createConnectionFactory());
    }
    protected abstract ConnectionFactory<?> createConnectionFactory();
    }

3.12 新建 QQAutoConfig,用于将QQ的配置注入到ConnectionFactory的构造参数中

package security.core.social.qq.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.social.connect.ConnectionFactory;
import security.core.properties.QQProperties;
import security.core.properties.SecurityProperties;
import security.core.social.qq.connect.QQConnectionFactory;

/**

  • 用于将QQ的配置注入到ConnectionFactory的构造参数中
  • ConditionalOnProperty:作用是只有当系统中配置了appId时QQAutoConfig配置类才会生效
    */
    @Configuration
    @ConditionalOnProperty(value = “imooc.security.social.qq”,name = “appId”)
    public class QQAutoConfig extends SocialAutoConfigurerAdapter{

@Autowired
private SecurityProperties securityProperties;

/**

  • 在创建ConnectionFactory时将参数注入进去
  • @return
    */
    @Override
    protected ConnectionFactory<?> createConnectionFactory() {
    QQProperties qqconfig = securityProperties.getSocial().getQqProperties();
    return new QQConnectionFactory(qqconfig.getProvideId(),qqconfig.getAppId(),qqconfig.getAppSecret());
    }
    }

3.13 在application-browser.properties属性文件中加入

imooc.security.social.qq.appId =
imooc.security.social.qq.appSecret =

3.14 在过滤器链中加入SocialAuthenticationFilter过滤器

3.14.1、将SpringSocial的Bean写在SocialConfig

/**

  • SpringSocial的配置,这个Bean也可以挪到 BrowserSecurityConfig里
  • @return
    */
    @Bean
    public SpringSocialConfigurer imoocSecuritySocialConfig(){
    return new SpringSocialConfigurer();
    }
3.14.2、在SpringSecurity的过滤器链中加入SpringSocial的配置

//加入SpringSocialConfigurer的配置
@Autowired
private SpringSocialConfigurer socialConfigurer;
/************************************************/
.apply(socialConfigurer).and()//将SpringSocial的过滤器配置加入其中

BrowserSecurityConfig的完整代码:

package security.browser.config;

import imooc.security.msn.service.MessageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.social.security.SpringSocialConfigurer;
import security.core.authentication.handle.MsnCodeAuthenticationFailureHandler;
import security.core.authentication.handle.MsnCodeAuthenticationSuccessHandler;
import security.core.authentication.mobile.MsnCodeAuthenticationSecurityConfig;
import security.core.properties.SecurityProperties;
import security.core.validateCode.ImageCodeGenerator;
import security.core.validateCode.ValidateCodeFilter;
import security.core.validateCode.ValidateCodeGenerator;

import javax.sql.DataSource;

/**

  • WebSecurityConfigurerAdapter是SpringSecurity提供的安全适配器类
    */
    @Configuration
    public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {

/**

  • 读取配置信息
    */
    @Autowired
    private SecurityProperties securityProperties;

/**

  • 自定义的登陆成功的处理器
    */
    @Autowired
    private AuthenticationSuccessHandler imoocAuthenticationSuccessHandler;

/**

  • 自定义的登陆失败的处理器
    */
    @Autowired
    private AuthenticationFailureHandler imoocAuthenticationFailureHandler;

@Autowired
private MsnCodeAuthenticationSecurityConfig msnCodeAuthenticationSecurityConfig;

//加入SpringSocialConfigurer的配置
@Autowired
private SpringSocialConfigurer socialConfigurer;

@Override
public void configure(WebSecurity web) throws Exception {
//解决静态资源被SpringSecurity拦截的问题
// “/static/“的意思是任何以 static地址开头的资源都能被访问
web.ignoring().antMatchers(”/static/
”,“/jquery/“,”/layui/”);
}
/**
*

  • @param http
  • @throws Exception
    */
    @Override
    protected void configure(HttpSecurity http) throws Exception {

//加入图片验证码的前置校验过滤器
ValidateCodeFilter validateCodeFilter = new ValidateCodeFilter();
validateCodeFilter.setAuthenticationFailureHandler(imoocAuthenticationFailureHandler);
//设置可配置的拦截url
validateCodeFilter.setSecurityProperties(securityProperties);
validateCodeFilter.afterPropertiesSet();

http.apply(msnCodeAuthenticationSecurityConfig).and()
.apply(socialConfigurer).and()//将SpringSocial的过滤器配置加入其中
.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)
.formLogin()//开启表单登录(即对表单登录进行身份认证)
// http.formLogin()//开启表单登录(即对表单登录进行身份认证)
.loginPage(“/authentication/require”)//指定登录页面
.loginProcessingUrl(“/authentication/form”)//让UsernamePasswordAuthenticationFilter能够处理提交的登录请求
.successHandler(imoocAuthenticationSuccessHandler)
.failureHandler(imoocAuthenticationFailureHandler)
// .and()
// .rememberMe()
// .tokenRepository(persistentTokenRepository())
// .tokenValiditySeconds(securityProperties.getBrowser().getRememberMeSecond())
// .userDetailsService(userDetailsService)
// http.httpBasic()//开启SpringSecurity原生的表单登录
.and()
.authorizeRequests()//对请求进行授权(即登录后需要授权)
.antMatchers(“/authentication/require”,“/authentication/mobile”,
securityProperties.getBrowser().getLoginPage(),
“/code/*”).permitAll()//允许signIn.html请求进来,不进行拦截
.anyRequest()//对任何请求
.authenticated()//开启认证
.and()
.csrf() //跨域请求伪造
.disable();//关闭

// .anyRequest()
// .authenticated();
// 上面两个方法的意思:对任何请求都需要认证

}

@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}

@Bean
public ValidateCodeGenerator imageCodeGenerator(){
return new ImageCodeGenerator();
}

// @Autowired
// private DataSource dataSource;
//
// @Autowired
// private UserDetailsService userDetailsService;
//
// @Bean
// public PersistentTokenRepository persistentTokenRepository(){
// JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
// tokenRepository.setDataSource(dataSource);
tokenRepository.setCreateTableOnStartup(true);
// return tokenRepository;
// }

/**

  • 消息服务的Bean
  • @return
    */
    @Bean
    public MessageService messageService(){
    return new MessageService();
    }

@Bean
public MsnCodeAuthenticationSecurityConfig getMsnCodeAuthenticationSecurityConfig(){
return new MsnCodeAuthenticationSecurityConfig();
}

@Bean
public MsnCodeAuthenticationSuccessHandler getMsnCodeAuthenticationSuccessHandler(){
return new MsnCodeAuthenticationSuccessHandler();
}

@Bean
public MsnCodeAuthenticationFailureHandler getMsnCodeAuthenticationFailureHandler(){
return new MsnCodeAuthenticationFailureHandler();
}

/**

  • SpringSocial的配置,这个Bean也可以挪到 BrowserSecurityConfig里
  • @return

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Go)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
onSecurityConfig getMsnCodeAuthenticationSecurityConfig(){
return new MsnCodeAuthenticationSecurityConfig();
}

@Bean
public MsnCodeAuthenticationSuccessHandler getMsnCodeAuthenticationSuccessHandler(){
return new MsnCodeAuthenticationSuccessHandler();
}

@Bean
public MsnCodeAuthenticationFailureHandler getMsnCodeAuthenticationFailureHandler(){
return new MsnCodeAuthenticationFailureHandler();
}

/**

  • SpringSocial的配置,这个Bean也可以挪到 BrowserSecurityConfig里
  • @return

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Go)
[外链图片转存中…(img-lKmaBeMr-1713416713404)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值