报错具体行为是PC端第三方登陆的链接显示未授权,跳转到自定义授权接口。
原因:
SpringBoot升级到2.X之后缺失social包,其中需要用到的是三个SocialWebAutoConfiguration
、SocialAutoConfigurerAdapter
以及SocialProperties
,其中SocialProperties
是参数配置,已经自行定义,此处不再需要,剩下的就只需要将1.5.6版本的这两个配置类拷贝到当前项目中即可,其中SocialWebAutoConfiguration类中可能会报SpringResourceResourceResolver.class
无法引入,注释掉相应的方法即可。
拷贝完成之后的代码(自行放至位置,在扫描范围内即可):
SocialAutoConfigurerAdapter.java:
package com.cong.security.core.social.support;
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;
/**
* @Description TODO
* @Author single-聪
* @Date 2020/1/17 14:42
* @Version 1.0.1
**/
public abstract class SocialAutoConfigurerAdapter extends SocialConfigurerAdapter {
public SocialAutoConfigurerAdapter() {
}
public void addConnectionFactories(ConnectionFactoryConfigurer configurer, Environment environment) {
configurer.addConnectionFactory(this.createConnectionFactory());
}
protected abstract ConnectionFactory<?> createConnectionFactory();
}
SocialWebAutoConfiguration.java:
package com.cong.security.core.social.support;
import java.util.List;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.social.UserIdSource;
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.ConnectionRepository;
import org.springframework.social.connect.UsersConnectionRepository;
import org.springframework.social.connect.web.ConnectController;
import org.springframework.social.connect.web.ConnectInterceptor;
import org.springframework.social.connect.web.DisconnectInterceptor;
import org.springframework.social.connect.web.ProviderSignInController;
import org.springframework.social.connect.web.ProviderSignInInterceptor;
import org.springframework.social.connect.web.SignInAdapter;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.servlet.view.BeanNameViewResolver;
/**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Social's web connection
* support.
*
* @author Craig Walls
* @since 1.1.0
*/
@Configuration
@ConditionalOnClass({ ConnectController.class, SocialConfigurerAdapter.class })
@ConditionalOnBean({ ConnectionFactoryLocator.class, UsersConnectionRepository.class })
@AutoConfigureBefore(ThymeleafAutoConfiguration.class)
@AutoConfigureAfter(WebMvcAutoConfiguration.class)
public class SocialWebAutoConfiguration {
@Configuration
@EnableSocial
@ConditionalOnWebApplication
protected static class SocialAutoConfigurationAdapter
extends SocialConfigurerAdapter {
private final List<ConnectInterceptor<?>> connectInterceptors;
private final List<DisconnectInterceptor<?>> disconnectInterceptors;
private final List<ProviderSignInInterceptor<?>> signInInterceptors;
public SocialAutoConfigurationAdapter(
ObjectProvider<List<ConnectInterceptor<?>>> connectInterceptorsProvider,
ObjectProvider<List<DisconnectInterceptor<?>>> disconnectInterceptorsProvider,
ObjectProvider<List<ProviderSignInInterceptor<?>>> signInInterceptorsProvider) {
this.connectInterceptors = connectInterceptorsProvider.getIfAvailable();
this.disconnectInterceptors = disconnectInterceptorsProvider.getIfAvailable();
this.signInInterceptors = signInInterceptorsProvider.getIfAvailable();
}
@Bean
@ConditionalOnMissingBean(ConnectController.class)
public ConnectController connectController(
ConnectionFactoryLocator factoryLocator,
ConnectionRepository repository) {
ConnectController controller = new ConnectController(factoryLocator,
repository);
if (!CollectionUtils.isEmpty(this.connectInterceptors)) {
controller.setConnectInterceptors(this.connectInterceptors);
}
if (!CollectionUtils.isEmpty(this.disconnectInterceptors)) {
controller.setDisconnectInterceptors(this.disconnectInterceptors);
}
return controller;
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "spring.social", name = "auto-connection-views")
public BeanNameViewResolver beanNameViewResolver() {
BeanNameViewResolver viewResolver = new BeanNameViewResolver();
viewResolver.setOrder(Ordered.HIGHEST_PRECEDENCE);
return viewResolver;
}
@Bean
@ConditionalOnBean(SignInAdapter.class)
@ConditionalOnMissingBean
public ProviderSignInController signInController(
ConnectionFactoryLocator factoryLocator,
UsersConnectionRepository usersRepository, SignInAdapter signInAdapter) {
ProviderSignInController controller = new ProviderSignInController(
factoryLocator, usersRepository, signInAdapter);
if (!CollectionUtils.isEmpty(this.signInInterceptors)) {
controller.setSignInInterceptors(this.signInInterceptors);
}
return controller;
}
}
@Configuration
@EnableSocial
@ConditionalOnWebApplication
@ConditionalOnMissingClass("org.springframework.security.core.context.SecurityContextHolder")
protected static class AnonymousUserIdSourceConfig extends SocialConfigurerAdapter {
@Override
public UserIdSource getUserIdSource() {
return new UserIdSource() {
@Override
public String getUserId() {
return "anonymous";
}
};
}
}
@Configuration
@EnableSocial
@ConditionalOnWebApplication
@ConditionalOnClass(SecurityContextHolder.class)
protected static class AuthenticationUserIdSourceConfig
extends SocialConfigurerAdapter {
@Override
public UserIdSource getUserIdSource() {
return new SecurityContextUserIdSource();
}
}
// @Configuration
// @ConditionalOnClass(SpringResourceResourceResolver.class)
// protected static class SpringSocialThymeleafConfig {
//
// @Bean
// @ConditionalOnMissingBean
// public SpringSocialDialect springSocialDialect() {
// return new SpringSocialDialect();
// }
//
// }
private static class SecurityContextUserIdSource implements UserIdSource {
@Override
public String getUserId() {
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();
Assert.state(authentication != null,
"Unable to get a " + "ConnectionRepository: no user signed in");
return authentication.getName();
}
}
}
最后还需要改的一个东西是QQAutoConfig.java
:
package com.cong.security.core.social;
import javax.sql.DataSource;
import com.cong.security.core.properties.SecurityProperties;
import com.cong.security.core.social.qq.connect.QQConnectionFactory;
import com.cong.security.core.social.support.SocialAutoConfigurerAdapter;
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;
/**
* 如果系统中没有配置QQ的appId以及appSecret,此配置不起作用
*
* @author single-聪
*/
@Configuration
@ConditionalOnProperty(prefix = "my.security.social.qq", name = "app-id")
public class QQAutoConfig extends SocialAutoConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Autowired
private SecurityProperties securityProperties;
protected ConnectionFactory<?> createConnectionFactory() {
// 创建连接工厂,初始化参数
return new QQConnectionFactory(securityProperties.getSocial().getQq().getProviderId(), securityProperties.getSocial().getQq().getAppId(), securityProperties.getSocial().getQq().getAppSecret());
}
}