package com.zcw.demospringsecurity.demo16;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import java.util.ArrayList;
import java.util.List;
public class JacksonFromTextHtmlHttpMessageConverter extends MappingJackson2HttpMessageConverter {
public JacksonFromTextHtmlHttpMessageConverter(){
List mediaTypes = new ArrayList();
mediaTypes.add(MediaType.TEXT_HTML);
setSupportedMediaTypes(mediaTypes);
}
}
package com.zcw.demospringsecurity.demo16;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class MYQQUserInfo {
private String nickname;
@JsonInclude("figureurl")
private String figureUrl30;
@JsonProperty("figureurl_1")
private String figureUrl50;
@JsonProperty("figureurl_2")
private String figureUrl100;
private String gender;
@JsonProperty("figureurl_qq_1")
private String qqFigureUrl40;
@JsonProperty("figureurl_qq_2")
private String qqFigureUrl100;
private String openId;
}
package com.zcw.demospringsecurity.demo16;
public interface QQ {
MYQQUserInfo getUserInfo();
}
package com.zcw.demospringsecurity.demo16;
import org.springframework.social.connect.ApiAdapter;
import org.springframework.social.connect.ConnectionValues;
import org.springframework.social.connect.UserProfile;
public class QQAdapter implements ApiAdapter<QQ> {
@Override
public boolean test(QQ qq){
return true;
}
@Override
public void setConnectionValues(QQ qq, ConnectionValues connectionValues){
MYQQUserInfo myqqUserInfo = qq.getUserInfo();
connectionValues.setProviderUserId(myqqUserInfo.getOpenId());
connectionValues.setDisplayName(myqqUserInfo.getNickname());
connectionValues.setImageUrl(myqqUserInfo.getQqFigureUrl100());
connectionValues.setProfileUrl(null);
}
@Override
public UserProfile fetchUserProfile(QQ qq){
return null;
}
@Override
public void updateStatus(QQ qq,String s){
}
}
package com.zcw.demospringsecurity.demo16;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties("spring.social.qq")
public class QQConfig {
private String providerId="qq";
private String appId;
private String appSecret;
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 getProviderId(){
return providerId;
}
public void setProviderId(String providerId){
this.providerId = providerId;
}
}
package com.zcw.demospringsecurity.demo16;
import org.springframework.social.connect.support.OAuth2ConnectionFactory;
public class QQConnectionFactory extends OAuth2ConnectionFactory<QQ> {
public QQConnectionFactory(String providerId,String appId,String appSecret ){
super(providerId,new QQServiceProvider(appId,appSecret),new QQAdapter());
}
}
package com.zcw.demospringsecurity.demo16;
import org.springframework.social.oauth2.AbstractOAuth2ApiBinding;
import org.springframework.web.client.RestTemplate;
public class QQImpl extends AbstractOAuth2ApiBinding implements QQ {
//获取openId的API
private static final String QQ_URL_GET_OPENID = "https://graph.qq.com/oauth2.0/me?access_token={accessToken}";
//获取用户信息的API
private static final String QQ_URL_GET_USER_INFO = "https://graph.qq.com/user/get_user_info?oauth_consumer_key={appId}&openid={openId}";
private String appId;
private String openId;
//构造函数在accessToken获取之后被调用,此处可以初始化openID
public QQImpl(String accessToken,String appId){
//accwss_token 作为查询参数被携带
//获取用户信息接口,无须声明携带accessToken,所有资源交互接口都会自行携带
this.appId = appId;
//获取openID接口响应
String result = getRestTemplate().getForObject(QQ_URL_GET_OPENID,String.class,accessToken);
//提取openid
this.openId = result.substring(result.lastIndexOf(":\"")+2,result.indexOf("\"}"));
}
@Override
public MYQQUserInfo getUserInfo(){
MYQQUserInfo myqqUserInfo = getRestTemplate().getForObject(QQ_URL_GET_USER_INFO,MYQQUserInfo.class,appId,
openId);
//为用户信息类补充openId
if(myqqUserInfo !=null){
myqqUserInfo.setOpenId(openId);
}
return myqqUserInfo;
}
@Override
protected void configureRestTemplate(RestTemplate restTemplate){
//为API交互的RestTemplate实例添加 text/heml 转JSON对象的支持
restTemplate.getMessageConverters().add(new JacksonFromTextHtmlHttpMessageConverter());
}
}
package com.zcw.demospringsecurity.demo16;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.social.connect.ConnectionFactory;
@Configuration
public class QQOAuth2Config extends SocialAutoConfigurerAdapter{
@Autowired
private QQConfig qqConfig;
@Override
protected ConnectionFactory<?> createConnectionFactory() {
return new QQConnectionFactory(qqConfig.getProviderId(),qqConfig.getAppId(),qqConfig.getAppSecret());
}
}
package com.zcw.demospringsecurity.demo16;
import org.springframework.social.oauth2.AccessGrant;
import org.springframework.social.oauth2.OAuth2Template;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
public class QQOAuth2Template extends OAuth2Template {
public QQOAuth2Template(String clientId,String clientSecret,String authorizeUrl,String accessTokenUrl){
super(clientId,clientSecret,authorizeUrl,accessTokenUrl);
setUseParametersForClientAuthentication(true);
}
@Override
protected AccessGrant postForAccessGrant(String accessTokenUrl, MultiValueMap<String,String> parameters){
String responseStr = getRestTemplate().postForObject(accessTokenUrl,parameters,String.class);
String[]items = responseStr.split("&");
String accessToken = items[0].substring(items[0].lastIndexOf("=")+1);
Long expiresIn = new Long(items[1].substring(items[1].lastIndexOf("=") +1));
String refreshToken = items[2].substring(items[2].lastIndexOf("=")+1);
return new AccessGrant(accessToken,null,refreshToken,expiresIn);
}
@Override
protected RestTemplate createRestTemplate(){
RestTemplate restTemplate =super.createRestTemplate();
restTemplate.getMessageConverters().add(
new TextHtmlHttpMessageConverter()
);
return restTemplate;
}
}
package com.zcw.demospringsecurity.demo16;
import org.springframework.social.oauth2.AbstractOAuth2ServiceProvider;
public class QQServiceProvider extends AbstractOAuth2ServiceProvider<QQ> {
private static final String QQ_URL_AUTHORIZE ="https://graph.qq.com/oauth2.0/authorize";
private static final String QQ_URL_ACCESS_TOKEN="https://graph.qq.com/oauth2.0/token";
private String appId;
public QQServiceProvider(String appId,String appSecret){
super(new QQOAuth2Template(appId,appSecret,QQ_URL_AUTHORIZE,QQ_URL_ACCESS_TOKEN));
this.appId = appId;
}
@Override
public QQ getApi(String accessToken){
return new QQImpl(accessToken,appId);
}
}
package com.zcw.demospringsecurity.demo16;
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;
public abstract class SocialAutoConfigurerAdapter extends SocialConfigurerAdapter {
public SocialAutoConfigurerAdapter() {
}
public void addConnectionFactories(ConnectionFactoryConfigurer configurer, Environment environment) {
configurer.addConnectionFactory(this.createConnectionFactory());
}
protected abstract ConnectionFactory<?> createConnectionFactory();
}
package com.zcw.demospringsecurity.demo16;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.util.StreamUtils;
import java.io.IOException;
import java.nio.charset.Charset;
public class TextHtmlHttpMessageConverter extends AbstractHttpMessageConverter {
public TextHtmlHttpMessageConverter(){
super(Charset.forName("UTF-8"),new MediaType[]{MediaType.TEXT_HTML});
}
@Override
protected boolean supports(Class clazz){
return String.class == clazz;
}
@Override
protected Object readInternal(Class aClass, HttpInputMessage httpInputMessage)
throws IOException, HttpMessageNotReadableException{
Charset charset = this.getContentTypeCharset(httpInputMessage.getHeaders().getContentType());
return StreamUtils.copyToString(httpInputMessage.getBody(),charset);
}
private Charset getContentTypeCharset(MediaType contentType){
return contentType !=null && contentType.getCharset() !=null ?contentType.getCharset():this.getDefaultCharset();
}
@Override
protected void writeInternal(Object o, HttpOutputMessage httpOutputMessage)
throws IOException, HttpMessageNotWritableException {
}
}