因为JAVA的Base64实现和Ruby不同,在使用SSO时会有异常,根据meta.discoursecn.org管理员的指点及资料查阅和代码分析,实现如下:
<%@ page contentType="text/html; charset=utf-8" %>
<%@ page import="org.apache.commons.codec.binary.Base64" %>
<%@ page import="org.apache.commons.codec.binary.Hex" %>
<%@ page import="javax.crypto.Mac" %>
<%@ page import="javax.crypto.spec.SecretKeySpec" %>
<%@ page import="java.io.UnsupportedEncodingException" %>
<%@ page import="java.net.URLDecoder" %>
<%@ page import="java.net.URLEncoder" %>
<%@ page import="java.security.InvalidKeyException" %>
<%@ page import="java.security.NoSuchAlgorithmException" %>
<%
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", -1);
Info info = (Info) session.getAttribute("Info");
if (info == null) {
response.sendRedirect("login.html");
return;
}
String key = "yourssosecret";
String payload = request.getParameter("sso");
String sig = request.getParameter("sig");
if (payload == null || sig == null) {
response.getWriter().println("error parameter");
return;
}
if (!checksum(key, payload).equals(sig)) {
response.getWriter().println("checksum failed");
return;
}
String urlDecode = URLDecoder.decode(payload, "UTF-8");
String nonce = new String(Base64.decodeBase64(urlDecode));
String urlEncode = nonce
+ "&name=" + URLEncoder.encode(info.name, "UTF-8")
+ "&username=" + URLEncoder.encode(info.nickname, "UTF-8")
+ "&email=" + URLEncoder.encode(info.email, "UTF-8")
+ "&external_id=" + URLEncoder.encode(info.id + "", "UTF-8");
String urlBase64 = new String(Base64.encodeBase64(urlEncode.getBytes("UTF-8")));
int length = 0;
int maxLength = urlBase64.length();
final int STEP = 60;
String urlBase64Encode = "";
while (length < maxLength) {
urlBase64Encode += urlBase64.substring(length, length + STEP < maxLength ? length + STEP : maxLength) + "\n";
length += STEP;
}
response.sendRedirect("http://yoursite.com/session/sso_login?sso=" + URLEncoder.encode(urlBase64Encode, "UTF-8") + "&sig=" + checksum(key, urlBase64Encode));
%>
<%!
String checksum(String macKey, String macData) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
Mac mac = Mac.getInstance("HmacSHA256");
byte[] keyBytes = macKey.getBytes("UTF-8");
byte[] dataBytes = macData.getBytes("UTF-8");
SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "HmacSHA256");
mac.init(secretKey);
byte[] doFinal = mac.doFinal(dataBytes);
byte[] hexBytes = new Hex().encode(doFinal);
return new String(hexBytes);
}
%>