zoukankan      html  css  js  c++  java
  • CAS Server集成QQ登录、新浪微博登录源码及配置文件

    转载自素文宅博客:https://blog.yoodb.com/yoodb/article/detail/1446

    CAS Server集成QQ第三方登录,CAS Server集成新浪微博第三方登录以及CAS Server集成微信网页登录源码和配置基本类似,本文着重介绍一下如何通过CAS Server(cas-server3.5.2)实现qq第三方登录,并分享一下实现代码和具体配置文件内容,虽然包含新浪微博登录但是未经测试,有什么疑问可留言。

    首先简单介绍一下CAS Server,它是一套基于Java实现的服务,该服务以一个Java Web Application单独部署在与servlet2.3兼容的Web服务器上。由于CAS ClientCAS Server之间的交互采用Https协议,因此部署CAS Server的服务器还需要支持SSL协议。当SSL配置成功过后,像普通Web应用一样将CAS Server部署在服务器上就能正常运行了,也可通过手动修改配置取消对SSL协议的支持。

    cas-server集成QQ第三方登录

    1、打开cas-server工程中cas-server-support-oauth子项目,创建QQApi20.java类文件名称并继承DefaultApi20.java类,具体代码如下:

    package org.jasig.cas.support.oauth.qq;
    import org.jasig.cas.support.oauth.OAuthConstants;
    import org.scribe.builder.api.DefaultApi20;
    import org.scribe.model.OAuthConfig;
    import org.scribe.utils.OAuthEncoder;
    public class QQApi20 extends DefaultApi20 {
        private static String serverUrl = "";
        
        @Override
        public String getAccessTokenEndpoint() {
            return serverUrl + "/" + OAuthConstants.QQ_ACCESS_TOKEN_URL + "?grant_type=authorization_code";
        }
        
        @Override
        public String getAuthorizationUrl(final OAuthConfig config) {
            return String.format(serverUrl + "/" + OAuthConstants.AUTHORIZE_URL
            + "?client_id=%s&redirect_uri=%s&response_type=code", config.getApiKey(),
            OAuthEncoder.encode(config.getCallback()));
        }
        
        public static void setServerUrl(final String url) {
            serverUrl = url;
        }
    }

    2、创建QQProvider.java类文件名称并继承BaseOAuth20Provider.java类,具体代码如下:

    package org.jasig.cas.support.oauth.qq;
    
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.List;
    
    import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
    import org.apache.commons.httpclient.HttpClient;
    import org.apache.commons.httpclient.HttpException;
    import org.apache.commons.httpclient.methods.GetMethod;
    import org.apache.commons.httpclient.params.HttpMethodParams;
    import org.jasig.cas.support.oauth.OAuthConstants;
    import org.jasig.cas.support.oauth.entity.UserInfo;
    import org.jasig.cas.support.oauth.profile.QQWrapperProfile;
    import org.scribe.builder.ServiceBuilder;
    import org.scribe.model.Token;
    import org.scribe.up.profile.JsonHelper;
    import org.scribe.up.profile.UserProfile;
    import org.scribe.up.provider.BaseOAuth20Provider;
    import org.scribe.up.provider.BaseOAuthProvider;
    import org.springframework.orm.jpa.JpaTemplate;
    
    import com.fasterxml.jackson.databind.JsonNode;
    
    /**
     * This class is the OAuth provider to authenticate user in CAS server wrapping OAuth protocol.
     * 
     * @author Jerome Leleu
     * @since 3.5.0
     */
    public final class QQProvider extends BaseOAuth20Provider {
        
        private String serverUrl;
        
        private JpaTemplate jpaTemplate;
        
        @Override
        protected void internalInit() {
        	QQApi20.setServerUrl(this.serverUrl);
            this.service = new ServiceBuilder().provider(QQApi20.class).apiKey(this.key).apiSecret(this.secret)
                .callback(this.callbackUrl).build();
        }
        
        @Override
        protected String getProfileUrl() {
            return this.serverUrl + "/" + OAuthConstants.QQ_PROFILE_URL;
        }
        
    	@Override
        protected UserProfile extractUserProfile(final String body) {
        	
            final QQWrapperProfile userProfile = new QQWrapperProfile();
            String str = body.replace("callback( ", "").replace(" );", "");
            JsonNode json = JsonHelper.getFirstNode(str);
    		userProfile.setId(JsonHelper.get(json, QQWrapperProfile.ID));
    		userProfile.addAttribute(QQWrapperProfile.CLIENTID, JsonHelper.get(json, QQWrapperProfile.CLIENTID));
            return userProfile;
        }
    	
    	private static String getRandomStr(){
    		SimpleDateFormat formatter = new SimpleDateFormat ("MMddHHmmss");
    		Date curDate = new Date(System.currentTimeMillis());//获取当前时间
    		String str = formatter.format(curDate);
    		String cur = str.substring(0,2);
    		String cur2 = str.substring(2,4);
    		String temp = (Integer.parseInt(cur)+Integer.parseInt(cur2))+""+str.substring(4);
    		int cur_id = Integer.parseInt(temp.substring(0,4))+Integer.parseInt(temp.substring(4));
    		String randomstr ="y" + cur_id + (int)(Math.random()*10000);
    		return randomstr;
    	}
       
    	@SuppressWarnings({ "deprecation", "rawtypes" })
        @Override
        protected UserProfile getUserProfile(final Token accessToken) {
            final String body = sendRequestForData(accessToken, getProfileUrl());
            if (body == null) {
                return null;
            }
            final UserProfile profile = extractUserProfile(body);
            addAccessTokenToProfile(profile, accessToken);
            String url = "https://graph.qq.com/user/get_user_info?access_token="+accessToken.getToken()+"&oauth_consumer_key="+this.key+"&openid="+profile.getId();
            String response = getHttp(url);
            JsonNode json = JsonHelper.getFirstNode(response);
            String ret = json.get("ret").asText();
            if(ret != null && ret.equals("0")){
            	List list = jpaTemplate.find("from UserInfo where openid='"+profile.getId()+"'");
        		UserInfo userInfo = null;
        		if(list == null || list.isEmpty()){
        			userInfo = new UserInfo();
        			String nickName = json.get("nickname").asText();
        			nickName = nickName.replaceAll("[^0-9a-zA-Z\u4e00-\u9fa5]", "");
        			userInfo.setNickName(nickName);
        			userInfo.setAvatar(json.get("figureurl_qq_1").asText());
        			userInfo.setGender(json.get("gender").asText());
        			userInfo.setOpenId(profile.getId());
        			userInfo.setClientId((String)profile.getAttributes().get(QQWrapperProfile.CLIENTID));
        			userInfo.setUserName(getRandomStr());
        			userInfo.setCompleted(0);
        			if(userInfo.getNickName() == null || userInfo.getNickName().equals("")){
        				userInfo.setNickName(userInfo.getUserName());
        			}
        			userInfo.setCreateTime(new Date());
        			jpaTemplate.persist(userInfo);
        		}else{
        			userInfo = (UserInfo) list.get(0);
        			userInfo.setUpdateTime(new Date());
        			jpaTemplate.merge(userInfo);
        		}
        		profile.setId(userInfo.getUserName());
        		profile.addAttribute("userId",userInfo.getUserId());
        		profile.addAttribute("userName",userInfo.getUserName());
                profile.addAttribute("nickName",userInfo.getNickName());
                profile.addAttribute("avatar",userInfo.getAvatar());
                profile.addAttribute("gender",userInfo.getGender());
                profile.addAttribute("openId",userInfo.getOpenId());
                profile.addAttribute("clientId",userInfo.getClientId());
                profile.addAttribute("completed",userInfo.getCompleted());
            }
            return profile;
        }
        
        public static String getHttp(String url) {
    		String responseMsg = "";
    		HttpClient httpClient = new HttpClient();
    		GetMethod getMethod = new GetMethod(url);
    		getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,new DefaultHttpMethodRetryHandler());
    		try {
    			httpClient.executeMethod(getMethod);
    			ByteArrayOutputStream out = new ByteArrayOutputStream();
    			InputStream in = getMethod.getResponseBodyAsStream();
    			int len = 0;
    			byte[] buf = new byte[1024];
    			while((len=in.read(buf))!=-1){
    				out.write(buf, 0, len);
    			}
    			responseMsg = out.toString("UTF-8");
    		} catch (HttpException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		} finally {
    			//释放连接
    			getMethod.releaseConnection();
    		}
    		return responseMsg;
    	}
        
        public void setServerUrl(final String serverUrl) {
            this.serverUrl = serverUrl;
        }
        
        @Override
        protected BaseOAuthProvider newProvider() {
            final QQProvider newProvider = new QQProvider();
            newProvider.setServerUrl(this.serverUrl);
            return newProvider;
        }
    
    	public JpaTemplate getJpaTemplate() {
    		return jpaTemplate;
    	}
    
    	public void setJpaTemplate(JpaTemplate jpaTemplate) {
    		this.jpaTemplate = jpaTemplate;
    	}
        
        
    }

    3、在cas-server-webapp子项目中,打开applicationContext.xml文件,添加对应的oauth的clients信息并把clients增加到对应的org.pac4j.core.client.Clients中,具体配置内容下:

    <bean id="sinaWeibo" class="org.jasig.cas.support.oauth.sina.SinaWeiboProvider">
            <property name="key" value="xxxxxxxxxxxxxxxx" />  
            <property name="secret" value="xxxxxxxxxxxxxxxxxxxxxxxxxxxx" />
            <property name="serverUrl" value="https://api.weibo.com/oauth2"/>
            <property name="callbackUrl" value="http://api.yoodb.com" />  <!-- oauth10login -->
    </bean>
    <bean id="qq" class="org.jasig.cas.support.oauth.qq.QQProvider"><!--新浪微博bean配置,跳过-->
        <property name="jpaTemplate" ref="jpaTemplate"/>
        <property name="key" value="xxxxxxxxxxxx" />  
        <property name="secret" value="xxxxxxxxxxxxxxxxxxxx" />
        <property name="serverUrl" value="https://graph.qq.com/oauth2.0"/>
        <property name="callbackUrl" value="http://api.yoodb.com" />  <!-- oauth10login -->
    </bean>

    4、在cas-server-webapp子项目中,打开deployerConfigContext.xml文件,增加bean配置,具体配置内容下:

    <bean class="org.jasig.cas.support.oauth.OAuthConfiguration" id="oAuthConfiguration">
    <property name="loginUrl" value="http://api.yoodb.com"/>
    <property name="providers">         
                <list>           
                    <ref bean="sinaWeibo" /><!--新浪微博配置,跳过-->
                    <ref bean="qq" />                       
                </list>       
            </property>
    </bean>

    5、添加以下链接到登录页面casLoginView.jsp(ClientNameUrl这个属性是被OAuthConfiguration自动创建),也就是你自定义的Client类名加上Url。如我创建的类为QQProvider则对应的link名为QQProviderUrl,具体代码如下:

    <div class="row btn-row third-part">
                         	<p class="third_login"><span>第三方帐号登录</span></p>
                         	<a href="${QQProviderUrl}" class="qq"></a>
                          	<a href="javascript:alert('目前只有QQ登录可以使用!');" class="sina"></a> 
    <%--                       	<a href="${SinaWeiboProviderUrl}" class="sina"></a>  --%>
                          	<a href="javascript:alert('目前只有QQ登录可以使用!');" class="baidu"></a>
                          	<a href="javascript:alert('目前只有QQ登录可以使用!');" class="wechat"></a>
                         </div>

    cas-server集成新浪微博第三方登录

    1、打开cas-server工程中cas-server-support-oauth子项目,创建SinaWeiboApi20.java类文件名称并继承DefaultApi20.java类,具体代码如下:

    package org.jasig.cas.support.oauth.sina;
    
    import org.jasig.cas.support.oauth.OAuthConstants;
    import org.scribe.builder.api.DefaultApi20;
    import org.scribe.model.OAuthConfig;
    import org.scribe.utils.OAuthEncoder;
    
    public class SinaWeiboApi20 extends DefaultApi20 {
    	private static String serverUrl = "";
    
    	@Override
    	public String getAccessTokenEndpoint() {
    		return serverUrl + "/" + OAuthConstants.SINA_ACCESS_TOKEN_URL + "?";
    	}
    
    	@Override
    	public String getAuthorizationUrl(final OAuthConfig config) {
    		return String.format(serverUrl + "/" + OAuthConstants.AUTHORIZE_URL
    				+ "?client_id=%s&redirect_uri=%s&response_type=code", config.getApiKey(),
    				OAuthEncoder.encode(config.getCallback()));
    	}
    
    	public static void setServerUrl(final String url) {
    		serverUrl = url;
    	}
    }

    2、创建SinaWeiboProvider.java类文件名称并继承BaseOAuth20Provider.java类,具体代码如下:

    package org.jasig.cas.support.oauth.sina;
    
    import java.util.Iterator;
    
    import org.jasig.cas.support.oauth.OAuthConstants;
    import org.jasig.cas.support.oauth.profile.CasWrapperProfile;
    import org.scribe.builder.ServiceBuilder;
    import org.scribe.up.profile.JsonHelper;
    import org.scribe.up.profile.UserProfile;
    import org.scribe.up.provider.BaseOAuth20Provider;
    import org.scribe.up.provider.BaseOAuthProvider;
    
    import com.fasterxml.jackson.databind.JsonNode;
    
    /**
     * This class is the OAuth provider to authenticate user in CAS server wrapping OAuth protocol.
     * 
     * @author Jerome Leleu
     * @since 3.5.0
     */
    public final class SinaWeiboProvider extends BaseOAuth20Provider {
        
        private String serverUrl;
        
        @Override
        protected void internalInit() {
        	SinaWeiboApi20.setServerUrl(this.serverUrl);
            this.service = new ServiceBuilder().provider(SinaWeiboApi20.class).apiKey(this.key).apiSecret(this.secret)
                .callback(this.callbackUrl).build();
        }
        
        @Override
        protected String getProfileUrl() {
            return this.serverUrl + "/" + OAuthConstants.SINA_PROFILE_URL;
        }
        
        @Override
        protected UserProfile extractUserProfile(final String body) {
            final CasWrapperProfile userProfile = new CasWrapperProfile();
            JsonNode json = JsonHelper.getFirstNode(body);
            if (json != null) {
                userProfile.setId(JsonHelper.get(json, CasWrapperProfile.ID));
                json = json.get(CasWrapperProfile.ATTRIBUTES);
                if (json != null) {
                    final Iterator<JsonNode> nodes = json.iterator();
                    while (nodes.hasNext()) {
                        json = nodes.next();
                        final String attribute = json.fieldNames().next();
                        userProfile.addAttribute(attribute, JsonHelper.get(json, attribute));
                    }
                }
            }
            return userProfile;
        }
        
        public void setServerUrl(final String serverUrl) {
            this.serverUrl = serverUrl;
        }
        
        @Override
        protected BaseOAuthProvider newProvider() {
            final SinaWeiboProvider newProvider = new SinaWeiboProvider();
            newProvider.setServerUrl(this.serverUrl);
            return newProvider;
        }
    }

    cas-server集成新浪微博登录和在cas-server集成qq登录类似,参考一下(本文中已经增加新浪微博配置及步骤但未经过测试),此处省略。

  • 相关阅读:
    如何将Sphinx生成的html文档集成进入Django
    npm提速
    Django缓存系统设置
    Django模板与Vue.js冲突问题
    CentOS7下安装配置MariaDB
    Linux下多线程下载利器 axel
    raspbian调整键盘设置
    git@github.com: Permission denied (publickey). fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists.
    彻底弄懂rem,px高度如何在不同的手机屏幕下自动换算
    PHP性能优化利器:生成器 yield理解(百万数据导出引申)
  • 原文地址:https://www.cnblogs.com/MrYoodb/p/7656545.html
Copyright © 2011-2022 走看看