├── README.md └── kisso ├── .classpath ├── .gitignore ├── .project ├── .settings └── org.eclipse.m2e.core.prefs ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── github │ │ └── tuzip │ │ └── sso │ │ ├── AuthToken.java │ │ ├── CrossDomainHelper.java │ │ ├── KissoHelper.java │ │ ├── LoginHelper.java │ │ ├── SSOConfig.java │ │ ├── SSOConstant.java │ │ ├── SSOToken.java │ │ ├── Token.java │ │ ├── TokenCache.java │ │ ├── TokenCacheMap.java │ │ ├── client │ │ └── SSOHelper.java │ │ ├── common │ │ ├── Browser.java │ │ ├── CookieHelper.java │ │ ├── FileHashHelper.java │ │ ├── IpHelper.java │ │ ├── encrypt │ │ │ ├── AES.java │ │ │ ├── Encrypt.java │ │ │ ├── MD5.java │ │ │ └── RSA.java │ │ └── util │ │ │ ├── Base64Util.java │ │ │ ├── DateUtil.java │ │ │ ├── HttpUtil.java │ │ │ ├── PropertiesUtil.java │ │ │ ├── RandomUtil.java │ │ │ └── ReflectUtil.java │ │ ├── exception │ │ └── KissoException.java │ │ ├── filter │ │ ├── SSOFilter.java │ │ ├── WafFilter.java │ │ └── readme.txt │ │ └── waf │ │ ├── WafHelper.java │ │ ├── attack │ │ ├── SqlInjection.java │ │ ├── XSS.java │ │ └── readme.txt │ │ └── request │ │ └── WafRequestWrapper.java └── resources │ ├── crossdomain.txt │ └── sso.properties └── test └── java └── com └── github └── tuzip └── sso ├── TestDateUtil.java ├── TestJsonToken.java ├── TestRSA.java └── TestRandomUtil.java /README.md: -------------------------------------------------------------------------------- 1 | sso 2 | === 3 | 4 | kisso cookie sso framework 5 | 6 | 7 | Usage 8 | ==================== 9 | 10 | [kisso dependent libs](https://github.com/tuzip/kisso-libs) 11 | 12 | [kisso-test-sparkjava](https://github.com/tuzip/kisso-test-sparkjava) 13 | 14 | ![GitHub](https://raw.githubusercontent.com/tuzip/kisso-test-sparkjava/master/login.jpg "Kisso,login cookie") 15 | 16 | 17 | Supports 18 | ==================== 19 | 1、支持单点登录 20 | 21 | 2、支持登录Cookie缓存 22 | 23 | 3、支持防止 XSS攻击, SQL注入,脚本注入 24 | 25 | 4、支持Base64 / MD5 / AES / RSA 算法 26 | 27 | 5、支持浏览器客户端校验 28 | 29 | 6、支持Cookie参数配置及扩展 30 | 31 | 7、支持跨域登录,模拟登录 32 | 33 | 34 | Futures 35 | ==================== 36 | 1、支持模拟登录 37 | 2、支持跨域模拟登录 38 | 39 | copyright 40 | ==================== 41 | Apache License, Version 2.0 42 | -------------------------------------------------------------------------------- /kisso/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /kisso/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /.settings 3 | /.classpath 4 | -------------------------------------------------------------------------------- /kisso/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | kisso 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /kisso/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | #Tue Jun 17 18:08:54 CST 2014 2 | activeProfiles= 3 | eclipse.preferences.version=1 4 | resolveWorkspaceProjects=true 5 | version=1 6 | -------------------------------------------------------------------------------- /kisso/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.github.tuzip 6 | kisso 7 | 1.0.0-RELEASE 8 | jar 9 | 10 | kisso 11 | kisso is a lightweight Java SSO Framework and reusable components. 12 | http://maven.apache.org 13 | 14 | 15 | 16 | The Apache Software License, Version 2.0 17 | http://www.apache.org/licenses/LICENSE-2.0.txt 18 | 19 | 20 | 21 | 22 | 23 | hubin 24 | 243194995@qq.com 25 | 26 | 27 | 28 | 29 | UTF-8 30 | 2.5 31 | 1.7.7 32 | 1.2.4 33 | 1.50 34 | 1.1.41 35 | 36 | 37 | 38 | 39 | 40 | javax.servlet 41 | servlet-api 42 | ${servlet-api.version} 43 | provided 44 | 45 | 46 | 47 | org.slf4j 48 | slf4j-api 49 | ${slf4j-api.version} 50 | 51 | 52 | 53 | nl.bitwalker 54 | UserAgentUtils 55 | ${UserAgentUtils.version} 56 | 57 | 58 | 59 | org.bouncycastle 60 | bcprov-jdk14 61 | ${bcprov-jdk14.version} 62 | 63 | 64 | 65 | com.alibaba 66 | fastjson 67 | ${fastjson.version} 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | org.apache.maven.plugins 77 | maven-source-plugin 78 | 2.2.1 79 | 80 | 81 | package 82 | 83 | jar-no-fork 84 | 85 | 86 | 87 | 88 | 89 | 90 | org.apache.maven.plugins 91 | maven-javadoc-plugin 92 | 2.9.1 93 | 94 | 95 | package 96 | 97 | jar 98 | 99 | 100 | 101 | 102 | 103 | 104 | org.apache.maven.plugins 105 | maven-gpg-plugin 106 | 1.5 107 | 108 | 109 | verify 110 | 111 | sign 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | oss 122 | https://oss.sonatype.org/content/repositories/snapshots/ 123 | 124 | 125 | oss 126 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/AuthToken.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso; 17 | 18 | import javax.servlet.http.HttpServletRequest; 19 | 20 | import com.github.tuzip.sso.common.IpHelper; 21 | import com.github.tuzip.sso.common.encrypt.RSA; 22 | import com.github.tuzip.sso.common.util.RandomUtil; 23 | import com.github.tuzip.sso.exception.KissoException; 24 | 25 | /** 26 | * SSO 跨域信任 Token 27 | *

28 | * @author hubin 29 | * @Date 2014-06-27 30 | */ 31 | public class AuthToken extends Token { 32 | private String userId;//用户ID 33 | private String uuid;//32 uuid 34 | private String randomId;//random number 35 | private String rsaSign;//ras sign 36 | 37 | @SuppressWarnings("unused") 38 | private AuthToken() { 39 | } 40 | 41 | /** 42 | * 有参构造函数 43 | * @param request 44 | * @param privateKey 45 | * RSA 密钥 46 | */ 47 | public AuthToken(HttpServletRequest request, String privateKey) { 48 | this.uuid = RandomUtil.get32UUID(); 49 | setUserIp(IpHelper.getIpAddr(request)); 50 | sign(privateKey); 51 | } 52 | 53 | /** 54 | * 生成签名字节数组 55 | * @return byte[] 56 | */ 57 | public byte[] signByte() { 58 | StringBuffer sb = new StringBuffer(getUuid()); 59 | sb.append("-").append(getUserIp()); 60 | return sb.toString().getBytes(); 61 | } 62 | 63 | /** 64 | * 设置签名 rsaSign 65 | * @param privateKey 66 | * RSA 密钥 67 | */ 68 | public void sign(String privateKey) { 69 | try { 70 | this.rsaSign = RSA.sign(signByte(), privateKey); 71 | } catch (Exception e) { 72 | e.printStackTrace(); 73 | throw new KissoException(" AuthToken RSA sign error. "); 74 | } 75 | } 76 | 77 | /** 78 | * 验证 AuthToken 签名是否合法 79 | * @param publicKey 80 | * RSA 公钥 81 | * @return 82 | */ 83 | public AuthToken verify(String publicKey) { 84 | try { 85 | /** 86 | * RSA 验证摘要 87 | * 是否合法 88 | */ 89 | if (RSA.verify(signByte(), publicKey, getRsaSign())) { 90 | return this; 91 | } 92 | } catch (Exception e) { 93 | e.printStackTrace(); 94 | throw new KissoException(" AuthToken RSA verify error. "); 95 | } 96 | return null; 97 | } 98 | 99 | public String getUserId() { 100 | return userId; 101 | } 102 | 103 | public void setUserId(String userId) { 104 | this.userId = userId; 105 | } 106 | 107 | public String getUuid() { 108 | return uuid; 109 | } 110 | public void setUuid(String uuid) { 111 | this.uuid = uuid; 112 | } 113 | public String getRandomId() { 114 | return randomId; 115 | } 116 | public void setRandomId(String randomId) { 117 | this.randomId = randomId; 118 | } 119 | public String getRsaSign() { 120 | return rsaSign; 121 | } 122 | public void setRsaSign(String rsaSign) { 123 | this.rsaSign = rsaSign; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/CrossDomainHelper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso; 17 | 18 | import javax.servlet.http.HttpServletRequest; 19 | import javax.servlet.http.HttpServletResponse; 20 | 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | import com.alibaba.fastjson.JSON; 25 | import com.github.tuzip.sso.common.CookieHelper; 26 | import com.github.tuzip.sso.common.encrypt.AES; 27 | import com.github.tuzip.sso.common.util.ReflectUtil; 28 | 29 | /** 30 | * Kisso 跨域帮助类 31 | *

32 | * 1、业务系统访问 SSO 保护系统、 验证未登录跳转至 SSO系统。 33 | * 2、SSO 设置信任Cookie 生成询问密文,通过代理页面 JSONP 询问业务系统是否允许登录。 34 | * 2、业务系统验证询问密文生成回复密文。 35 | * 3、代理页面 getJSON SSO 验证回复密文,SSO 根据 ok 返回 userId 查询绑定关系进行登录,通知代理页面重定向到访问页面。 36 | * @author hubin 37 | * @Date 2014-06-27 38 | */ 39 | public class CrossDomainHelper { 40 | private final static Logger logger = LoggerFactory.getLogger(CrossDomainHelper.class); 41 | 42 | /** 43 | * 设置跨域信任 Cookie 44 | * @param authToken 45 | * 跨域信任 Token 46 | */ 47 | public static void setAuthCookie(HttpServletRequest request, 48 | HttpServletResponse response, AuthToken authToken) { 49 | try { 50 | CookieHelper.addCookie( 51 | response, 52 | SSOConfig.getCookieDomain(), 53 | SSOConfig.getCookiePath(), 54 | SSOConfig.getAuthCookieName(), 55 | KissoHelper.encryptCookie(request, authToken, 56 | ReflectUtil.getConfigEncrypt()), 57 | SSOConfig.getAuthCookieMaxage(), true, 58 | SSOConfig.getCookieSecure()); 59 | } catch (Exception e) { 60 | e.printStackTrace(); 61 | logger.error("AuthToken encryptCookie error."); 62 | } 63 | } 64 | 65 | /** 66 | * 获取跨域信任 AuthToken 67 | * @param request 68 | * @param publicKey 69 | * RSA 公钥 (SSO) 70 | * @return 71 | */ 72 | public static AuthToken getAuthToken(HttpServletRequest request, String publicKey) { 73 | String jsonToken = KissoHelper.getJsonToken(request, 74 | ReflectUtil.getConfigEncrypt(), SSOConfig.getAuthCookieName()); 75 | if (jsonToken == null || "".equals(jsonToken)) { 76 | logger.info("jsonToken is null."); 77 | return null; 78 | } else { 79 | /** 80 | * 校验 IP 81 | * 合法返回 AuthToken 82 | */ 83 | AuthToken at = JSON.parseObject(jsonToken, AuthToken.class); 84 | if (KissoHelper.checkIp(request, at) == null) { 85 | return null; 86 | } 87 | return at.verify(publicKey); 88 | } 89 | } 90 | 91 | /** 92 | * 生成跨域询问密文 93 | * @param authToken 94 | * 跨域信任 Token 95 | * @param aesKey 96 | * AES 密钥 97 | */ 98 | public String askCiphertext(AuthToken authToken, String aesKey) { 99 | try { 100 | return new AES().encrypt(authToken.jsonToken(), aesKey); 101 | } catch (Exception e) { 102 | e.printStackTrace(); 103 | logger.info("askCiphertext AES encrypt error."); 104 | } 105 | return null; 106 | } 107 | 108 | /** 109 | * 生成跨域回复密文 110 | * @param authToken 111 | * 跨域信任 Token 112 | * @param userId 113 | * 用户ID 114 | * @param askTxt 115 | * 询问密文 116 | * @param privateKey 117 | * RSA 密钥 (业务系统) 118 | * @param publicKey 119 | * RSA 公钥 (SSO) 120 | * @param aesKey 121 | * AES 密钥 122 | */ 123 | public String replyCiphertext(HttpServletRequest request, String userId, 124 | String askTxt, String privateKey, String publicKey, String aesKey) { 125 | String at = null; 126 | try { 127 | at = new AES().decrypt(askTxt, aesKey); 128 | } catch (Exception e) { 129 | e.printStackTrace(); 130 | logger.info("replyCiphertext AES decrypt error."); 131 | } 132 | if (at != null) { 133 | AuthToken authToken = JSON.parseObject(at, AuthToken.class); 134 | if (KissoHelper.checkIp(request, authToken.verify(publicKey)) != null) { 135 | authToken.setUserId(userId); 136 | try { 137 | /** 138 | * 使用业务系统密钥 139 | * 重新签名 140 | */ 141 | authToken.sign(privateKey); 142 | return new AES().encrypt(authToken.jsonToken(), aesKey); 143 | } catch (Exception e) { 144 | e.printStackTrace(); 145 | logger.info("replyCiphertext AES encrypt error."); 146 | } 147 | } 148 | } 149 | return null; 150 | } 151 | 152 | /** 153 | * 验证回复密文,成功! 返回绑定用户ID 154 | * @param request 155 | * @param response 156 | * @param authToken 157 | * 跨域信任 Token 158 | * @param askTxt 159 | * 询问密文 160 | * @param publicKey 161 | * RSA 公钥 (业务系统) 162 | * @param aesKey 163 | * AES 密钥 164 | * @return 用户ID 165 | */ 166 | public String ok(HttpServletRequest request, HttpServletResponse response, 167 | String replyTxt, String publicKey, String aesKey) { 168 | AuthToken authToken = getAuthToken(request, publicKey); 169 | if (authToken != null) { 170 | String rt = null; 171 | try { 172 | rt = new AES().decrypt(replyTxt, aesKey); 173 | } catch (Exception e) { 174 | e.printStackTrace(); 175 | logger.info("kisso AES decrypt error."); 176 | } 177 | if (rt != null) { 178 | AuthToken atk = JSON.parseObject(rt, AuthToken.class); 179 | if (atk != null && atk.getUserIp().equals(authToken.getUserIp())) { 180 | if (atk.verify(publicKey) != null) { 181 | /** 182 | * 删除跨域信任Cookie 183 | * 返回 userId 184 | */ 185 | CookieHelper.clearCookieByName(request, response, SSOConfig.getAuthCookieName(), 186 | SSOConfig.getCookieDomain(), SSOConfig.getCookiePath()); 187 | return atk.getUserId(); 188 | } 189 | } 190 | } 191 | } 192 | return null; 193 | } 194 | 195 | } 196 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/KissoHelper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso; 17 | 18 | import javax.servlet.http.Cookie; 19 | import javax.servlet.http.HttpServletRequest; 20 | 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | import com.github.tuzip.sso.common.Browser; 25 | import com.github.tuzip.sso.common.CookieHelper; 26 | import com.github.tuzip.sso.common.IpHelper; 27 | import com.github.tuzip.sso.common.encrypt.Encrypt; 28 | import com.github.tuzip.sso.common.util.RandomUtil; 29 | import com.github.tuzip.sso.exception.KissoException; 30 | 31 | /** 32 | * Kisso 帮助类 33 | *

34 | * @author hubin 35 | * @Date 2014-06-27 36 | */ 37 | public class KissoHelper { 38 | private final static Logger logger = LoggerFactory.getLogger(KissoHelper.class); 39 | 40 | /** 41 | * @Description 加密Token信息 42 | * @param request 43 | * @param token 44 | * SSO 登录信息票据 45 | * @param encrypt 46 | * 对称加密算法类 47 | * @return Cookie 登录信息Cookie 48 | */ 49 | public static String encryptCookie(HttpServletRequest request, Token token, 50 | Encrypt encrypt) throws Exception { 51 | if (token == null) { 52 | throw new KissoException(" Token not for null."); 53 | } 54 | /** 55 | * token加密混淆 56 | */ 57 | String jt = token.jsonToken(); 58 | StringBuffer sf = new StringBuffer(); 59 | sf.append(jt); 60 | sf.append(SSOConstant.CUT_SYMBOL); 61 | /** 62 | * 判断是否认证浏览器信息 63 | * 否取8位随机数混淆 64 | */ 65 | if (SSOConfig.getCookieBrowser()) { 66 | sf.append(Browser.getUserAgent(request, jt)); 67 | } else { 68 | sf.append(RandomUtil.getCharacterAndNumber(8)); 69 | } 70 | return encrypt.encrypt(sf.toString(), SSOConfig.getSecretKey()); 71 | } 72 | 73 | /** 74 | * 校验Token IP 与登录 IP 是否一致 75 | *

76 | * @param request 77 | * @param token 78 | * 登录票据 79 | * @return Token 80 | */ 81 | public static Token checkIp(HttpServletRequest request, Token token) { 82 | /** 83 | * 判断是否检查 IP 一致性 84 | */ 85 | if (SSOConfig.getCookieCheckip()) { 86 | String ip = IpHelper.getIpAddr(request); 87 | if (token != null && ip != null && !ip.equals(token.getUserIp())) { 88 | /** 89 | * 检查 IP 与登录IP 不一致返回 null 90 | */ 91 | logger.info("ip inconsistent! return token null, token userIp:{}, reqIp:{}", 92 | new Object[] { token.getUserIp(), ip }); 93 | return null; 94 | } 95 | } 96 | return token; 97 | } 98 | 99 | /** 100 | * 获取当前请求 JsonToken 101 | *

102 | * @param request 103 | * @param encrypt 104 | * 对称加密算法类 105 | * @param cookieName 106 | * Cookie名称 107 | * @return String 当前Token的json格式值 108 | */ 109 | public static String getJsonToken(HttpServletRequest request, Encrypt encrypt, String cookieName) { 110 | Cookie uid = CookieHelper.findCookieByName(request, cookieName); 111 | if (uid != null) { 112 | String jsonToken = uid.getValue(); 113 | String[] tokenAttr = new String[2]; 114 | try { 115 | jsonToken = encrypt.decrypt(jsonToken, SSOConfig.getSecretKey()); 116 | tokenAttr = jsonToken.split(SSOConstant.CUT_SYMBOL); 117 | } catch (Exception e) { 118 | logger.info("jsonToken decrypt error."); 119 | e.printStackTrace(); 120 | } 121 | /** 122 | * 判断是否认证浏览器 123 | * 混淆信息 124 | */ 125 | if (SSOConfig.getCookieBrowser()) { 126 | if (Browser.isLegalUserAgent(request, tokenAttr[0], tokenAttr[1])) { 127 | return tokenAttr[0]; 128 | } else { 129 | /** 130 | * 签名验证码失败 131 | */ 132 | logger.error("SSOHelper getToken, find Browser is illegal."); 133 | } 134 | } else { 135 | /** 136 | * 不需要认证浏览器信息混淆 137 | * 返回JsonToken 138 | */ 139 | return tokenAttr[0]; 140 | } 141 | } 142 | 143 | return null; 144 | } 145 | 146 | } 147 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/LoginHelper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso; 17 | 18 | import javax.servlet.http.Cookie; 19 | import javax.servlet.http.HttpServletRequest; 20 | import javax.servlet.http.HttpServletResponse; 21 | 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | 25 | import com.github.tuzip.sso.common.CookieHelper; 26 | import com.github.tuzip.sso.common.encrypt.Encrypt; 27 | import com.github.tuzip.sso.common.util.RandomUtil; 28 | import com.github.tuzip.sso.common.util.ReflectUtil; 29 | import com.github.tuzip.sso.exception.KissoException; 30 | 31 | /** 32 | * SSO登录帮助类 33 | *

34 | * @author hubin 35 | * @Date 2014-5-9 36 | */ 37 | public class LoginHelper { 38 | private final static Logger logger = LoggerFactory.getLogger(LoginHelper.class); 39 | 40 | /** 41 | * @Description 根据Token生成登录信息Cookie 42 | * @param request 43 | * @param token 44 | * SSO 登录信息票据 45 | * @param encrypt 46 | * 对称加密算法类 47 | * @return Cookie 登录信息Cookie 48 | */ 49 | private static Cookie generateCookie(HttpServletRequest request, 50 | Token token, Encrypt encrypt) { 51 | try { 52 | Cookie cookie = new Cookie(SSOConfig.getCookieName(), 53 | KissoHelper.encryptCookie(request, token, encrypt)); 54 | cookie.setPath(SSOConfig.getCookiePath()); 55 | cookie.setSecure(SSOConfig.getCookieSecure()); 56 | cookie.setDomain(SSOConfig.getCookieDomain()); 57 | /** 58 | * 设置Cookie超时时间 59 | */ 60 | int maxAge = SSOConfig.getCookieMaxage(); 61 | if (maxAge >= 0) { 62 | cookie.setMaxAge(maxAge); 63 | } 64 | return cookie; 65 | } catch (Exception e) { 66 | logger.error("generateCookie is exception!", e.toString()); 67 | return null; 68 | } 69 | } 70 | 71 | /** 72 | * @Description 当前访问域下设置登录Cookie 73 | * @param request 74 | * @param response 75 | * @param encrypt 76 | * 对称加密算法类 77 | */ 78 | private static void setSSOCookie(HttpServletRequest request, HttpServletResponse response, Token token, 79 | Encrypt encrypt) { 80 | if (encrypt == null) { 81 | throw new KissoException(" Encrypt not for null."); 82 | } 83 | try { 84 | Cookie ck = generateCookie(request, token, encrypt); 85 | if (SSOConfig.getCookieHttponly()) { 86 | /** 87 | * Cookie设置HttpOnly 88 | */ 89 | CookieHelper.addHttpOnlyCookie(response, ck); 90 | } else { 91 | response.addCookie(ck); 92 | } 93 | } catch (Exception e) { 94 | logger.error("set HTTPOnly cookie createAUID is exception!", e.toString()); 95 | } 96 | } 97 | 98 | /** 99 | * @Description 当前访问域下设置登录Cookie 100 | * @param request 101 | * @param response 102 | */ 103 | public static void setSSOCookie(HttpServletRequest request, HttpServletResponse response, Token token) { 104 | setSSOCookie(request, response, token, ReflectUtil.getConfigEncrypt()); 105 | } 106 | 107 | /** 108 | * @Description 当前访问域下设置登录Cookie 109 | * 设置防止伪造SESSIONID攻击 110 | * @param request 111 | * @param response 112 | */ 113 | public static void authSSOCookie(HttpServletRequest request, HttpServletResponse response, Token token) { 114 | CookieHelper.authJSESSIONID(request, RandomUtil.getCharacterAndNumber(8)); 115 | setSSOCookie(request, response, token); 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/SSOConfig.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso; 17 | 18 | import java.io.InputStream; 19 | import java.util.Properties; 20 | 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | import com.github.tuzip.sso.common.util.PropertiesUtil; 25 | 26 | /** 27 | * SSO 配置文件解析 28 | *

29 | * @author hubin 30 | * @Date 2014-5-12 31 | */ 32 | public class SSOConfig { 33 | private final static Logger logger = LoggerFactory.getLogger(SSOConfig.class); 34 | private static PropertiesUtil prop = null; 35 | 36 | static { 37 | /** 38 | * SSO 资源文件初始化 39 | */ 40 | if (prop == null) { 41 | InputStream in = SSOConfig.class.getResourceAsStream("/sso.properties"); 42 | Properties p = new Properties(); 43 | try { 44 | p.load(in); 45 | prop = new PropertiesUtil(p); 46 | } catch (Exception e) { 47 | logger.error("read sso.properties error. ", e.toString()); 48 | } 49 | } 50 | } 51 | 52 | /** 53 | * 编码格式默认 UTF-8 54 | */ 55 | public static String getEncoding() { 56 | return prop.get("sso.encoding", SSOConstant.ENCODING); 57 | } 58 | 59 | /** 60 | * 密钥 61 | */ 62 | public static String getSecretKey() { 63 | return prop.get("sso.secretkey", SSOConstant.SSO_SECRET_KEY); 64 | } 65 | 66 | /** 67 | * Cookie 只允许https协议传输 68 | */ 69 | public static boolean getCookieSecure() { 70 | return prop.getBoolean("sso.cookie.secure", SSOConstant.SSO_COOKIE_SECURE); 71 | } 72 | 73 | /** 74 | * Cookie 只读,不允许 Js访问 75 | */ 76 | public static boolean getCookieHttponly() { 77 | return prop.getBoolean("sso.cookie.httponly", SSOConstant.SSO_COOKIE_HTTPONLY); 78 | } 79 | 80 | /** 81 | * Cookie 超时时间 82 | */ 83 | public static int getCookieMaxage() { 84 | return prop.getInt("sso.cookie.maxage", SSOConstant.SSO_COOKIE_MAXAGE); 85 | } 86 | 87 | /** 88 | * Cookie 名称 89 | */ 90 | public static String getCookieName() { 91 | return prop.get("sso.cookie.name", SSOConstant.SSO_COOKIE_NAME); 92 | } 93 | 94 | /** 95 | * Cookie 所在域 96 | */ 97 | public static String getCookieDomain() { 98 | return prop.get("sso.cookie.domain", SSOConstant.SSO_COOKIE_DOMAIN); 99 | } 100 | 101 | /** 102 | * Cookie 域路径 103 | */ 104 | public static String getCookiePath() { 105 | return prop.get("sso.cookie.path", SSOConstant.SSO_COOKIE_PATH); 106 | } 107 | 108 | /** 109 | * Cookie 开启浏览器版本校验 110 | */ 111 | public static boolean getCookieBrowser() { 112 | return prop.getBoolean("sso.cookie.browser", SSOConstant.SSO_COOKIE_BROWSER); 113 | } 114 | 115 | /** 116 | * Cookie 开启IP校验 117 | */ 118 | public static boolean getCookieCheckip() { 119 | return prop.getBoolean("sso.cookie.checkip", SSOConstant.SSO_COOKIE_CHECKIP); 120 | } 121 | 122 | /** 123 | * Cookie 开启缓存 Token 124 | */ 125 | public static boolean getCookieCache() { 126 | return prop.getBoolean("sso.cookie.cache", SSOConstant.SSO_COOKIE_CACHE); 127 | } 128 | 129 | /** 130 | * 自定义Encrypt Class 131 | */ 132 | public static String getEncryptClass() { 133 | return prop.get("sso.encrypt.class", SSOConstant.SSO_ENCRYPT_CLASS); 134 | } 135 | 136 | /** 137 | * 自定义Token Class 138 | */ 139 | public static String getTokenClass() { 140 | return prop.get("sso.token.class", SSOConstant.SSO_TOKEN_CLASS); 141 | } 142 | 143 | /** 144 | * 自定义TokenCache Class 145 | */ 146 | public static String getTokenCacheClass() { 147 | return prop.get("sso.tokencache.class", SSOConstant.SSO_TOKENCACHE_CLASS); 148 | } 149 | 150 | /** 151 | * SSO 登录地址 152 | */ 153 | public static String getLoginUrl() { 154 | return prop.get("sso.login.url", SSOConstant.SSO_LOGIN_URL); 155 | } 156 | 157 | /** 158 | * 跨域信任 Cookie 名称 159 | */ 160 | public static String getAuthCookieName() { 161 | return prop.get("sso.crossdomain.cookie.name", SSOConstant.SSO_AUTH_COOKIE_NAME); 162 | } 163 | 164 | /** 165 | * 跨域信任 Cookie 超时时间 166 | */ 167 | public static int getAuthCookieMaxage() { 168 | return prop.getInt("sso.crossdomain.cookie.maxage", SSOConstant.SSO_AUTH_COOKIE_MAXAGE); 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/SSOConstant.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso; 17 | 18 | /** 19 | * SSO 常量定义 20 | *

21 | * @author hubin 22 | * @Date 2014-5-9 23 | */ 24 | public class SSOConstant { 25 | /** 26 | * 基本常量定义 27 | */ 28 | public final static String ENCODING = "UTF-8"; 29 | public final static String ALLCHAR = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 30 | public final static String SSO_SECRET_KEY = "h2wmABdfM7i3K80mAS"; 31 | public final static String CUT_SYMBOL = "#"; 32 | 33 | /** 34 | * Cookie 设置常量 35 | * maxage 介绍: 36 | * -1 浏览器关闭时自动删除 37 | * 0 立即删除 38 | * 120 表示Cookie有效期2分钟(以秒为单位) 39 | */ 40 | public final static boolean SSO_COOKIE_SECURE = false; 41 | public final static boolean SSO_COOKIE_HTTPONLY = true; 42 | public final static int SSO_COOKIE_MAXAGE = -1; 43 | public final static String SSO_COOKIE_NAME = "uid"; 44 | public final static String SSO_COOKIE_DOMAIN = ""; 45 | public final static String SSO_COOKIE_PATH = "/"; 46 | 47 | /** 48 | * SSO 登录 Cookie 校验常量 49 | */ 50 | public final static boolean SSO_COOKIE_BROWSER = true; 51 | public final static boolean SSO_COOKIE_CHECKIP = false; 52 | public final static boolean SSO_COOKIE_CACHE = false; 53 | 54 | /** 55 | * 自定义Encrypt Class 56 | */ 57 | public final static String SSO_ENCRYPT_CLASS = ""; 58 | /** 59 | * 自定义Token Class 60 | */ 61 | public final static String SSO_TOKEN_CLASS = ""; 62 | /** 63 | * 自定义TokenCache Class 64 | */ 65 | public final static String SSO_TOKENCACHE_CLASS = ""; 66 | 67 | /** 68 | * 登录相关常量 69 | */ 70 | public final static String SSO_LOGIN_URL = "sso.github.com"; 71 | 72 | /** 73 | * SSO 跨域相关常量 74 | * maxage 介绍: 75 | * -1 浏览器关闭时自动删除 76 | * 0 立即删除 77 | * 120 表示Cookie有效期2分钟(以秒为单位) 78 | */ 79 | public final static String SSO_AUTH_COOKIE_NAME = "pid"; 80 | public final static int SSO_AUTH_COOKIE_MAXAGE = 180; 81 | } 82 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/SSOToken.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso; 17 | 18 | import javax.servlet.http.HttpServletRequest; 19 | 20 | import com.github.tuzip.sso.common.IpHelper; 21 | 22 | /** 23 | * SSO登录标记Cookie基本信息对象 24 | *

25 | * @author hubin 26 | * @Date 2014-5-8 27 | */ 28 | public class SSOToken extends Token { 29 | private final static String DEFAULT_VALUE = "0";//默认参数值 30 | private String appId;//应用系统 ID 31 | private String userId;//用户 ID 32 | private String loginType;//登录类型 33 | private long loginTime;//登录时间 34 | 35 | public SSOToken() { 36 | 37 | } 38 | 39 | public SSOToken(HttpServletRequest request) { 40 | this.appId = DEFAULT_VALUE; 41 | setUserIp(IpHelper.getIpAddr(request)); 42 | this.loginType = DEFAULT_VALUE; 43 | this.loginTime = System.currentTimeMillis(); 44 | } 45 | 46 | public String getAppId() { 47 | return appId; 48 | } 49 | 50 | public void setAppId(String appId) { 51 | this.appId = appId; 52 | } 53 | 54 | public String getUserId() { 55 | return userId; 56 | } 57 | 58 | public void setUserId(String userId) { 59 | this.userId = userId; 60 | } 61 | 62 | public String getLoginType() { 63 | return loginType; 64 | } 65 | 66 | public void setLoginType(String loginType) { 67 | this.loginType = loginType; 68 | } 69 | 70 | public long getLoginTime() { 71 | return loginTime; 72 | } 73 | 74 | public void setLoginTime(long loginTime) { 75 | this.loginTime = loginTime; 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/Token.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso; 17 | 18 | import com.alibaba.fastjson.JSON; 19 | 20 | /** 21 | * SSO票据顶级父类 22 | *

23 | * @author hubin 24 | * @Date 2014-5-9 25 | */ 26 | public class Token { 27 | /** 28 | * 登录 IP 29 | */ 30 | private String userIp; 31 | 32 | /** 33 | * Token转为JSON格式 34 | *

35 | * @return JSON格式Token值 36 | */ 37 | public String jsonToken() { 38 | return JSON.toJSONString(this); 39 | } 40 | 41 | /** 42 | * JSON格式Token值转为Token对象 43 | *

44 | * @param jsonToken 45 | * JSON格式Token值 46 | * @return Token对象 47 | */ 48 | public Token parseToken(String jsonToken) { 49 | return JSON.parseObject(jsonToken, this.getClass()); 50 | } 51 | 52 | public String getUserIp() { 53 | return userIp; 54 | } 55 | 56 | public void setUserIp(String userIp) { 57 | this.userIp = userIp; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/TokenCache.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso; 17 | 18 | /** 19 | * Token 缓存父类 20 | *

21 | * @author hubin 22 | * @Date 2014-6-17 23 | */ 24 | public abstract class TokenCache { 25 | 26 | /** 27 | * 根据key获取SSO票据 28 | *

29 | * @param key 关键词 30 | * @return Token SSO票据 31 | */ 32 | public abstract Token get(String key); 33 | 34 | /** 35 | * 设置SSO票据 36 | *

37 | * @param key 关键词 38 | */ 39 | public abstract void set(String key, Token token); 40 | 41 | /** 42 | * 删除SSO票据 43 | *

44 | * @param key 关键词 45 | */ 46 | public abstract void delete(String key); 47 | } 48 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/TokenCacheMap.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso; 17 | 18 | import java.util.HashMap; 19 | 20 | /** 21 | * Token缓存到HashMap 22 | *

23 | * @author hubin 24 | * @Date 2014-6-17 25 | */ 26 | public class TokenCacheMap extends TokenCache { 27 | /** 28 | * Token Map 29 | */ 30 | private static HashMap tokenMap = new HashMap(); 31 | 32 | /** 33 | * 根据key获取SSO票据 34 | *

35 | * @param key 关键词 36 | * @return Token SSO票据 37 | */ 38 | @Override 39 | public Token get(String key) { 40 | return tokenMap.get(key); 41 | } 42 | 43 | /** 44 | * 设置SSO票据 45 | *

46 | * @param key 关键词 47 | */ 48 | @Override 49 | public void set(String key, Token token) { 50 | tokenMap.put(key, token); 51 | } 52 | 53 | /** 54 | * 删除SSO票据 55 | *

56 | * @param key 关键词 57 | */ 58 | @Override 59 | public void delete(String key) { 60 | tokenMap.remove(key); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/client/SSOHelper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso.client; 17 | 18 | import java.io.IOException; 19 | 20 | import javax.servlet.http.Cookie; 21 | import javax.servlet.http.HttpServletRequest; 22 | import javax.servlet.http.HttpServletResponse; 23 | 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | 27 | import com.github.tuzip.sso.KissoHelper; 28 | import com.github.tuzip.sso.SSOConfig; 29 | import com.github.tuzip.sso.Token; 30 | import com.github.tuzip.sso.TokenCache; 31 | import com.github.tuzip.sso.common.CookieHelper; 32 | import com.github.tuzip.sso.common.encrypt.Encrypt; 33 | import com.github.tuzip.sso.common.util.HttpUtil; 34 | import com.github.tuzip.sso.common.util.ReflectUtil; 35 | import com.github.tuzip.sso.exception.KissoException; 36 | 37 | /** 38 | * SSO客户端帮助类 39 | *

40 | * @author hubin 41 | * @Date 2014-5-8 42 | */ 43 | public class SSOHelper { 44 | private final static Logger logger = LoggerFactory.getLogger(SSOHelper.class); 45 | 46 | /** 47 | * 获取当前请求 Token 48 | *

49 | * @param request 50 | * @return 51 | * @return Token 52 | */ 53 | public static Token getToken(HttpServletRequest request) { 54 | return getToken(request, ReflectUtil.getConfigEncrypt(), ReflectUtil.getConfigTokenCache()); 55 | } 56 | 57 | /** 58 | * 获取当前请求 Token 59 | *

60 | * @param request 61 | * @param encrypt 62 | * 对称加密算法类 63 | * @return Token 64 | */ 65 | private static Token getToken(HttpServletRequest request, Encrypt encrypt, TokenCache cache) { 66 | if (cache == null) { 67 | throw new KissoException(" TokenCache not for null."); 68 | } 69 | if (encrypt == null) { 70 | throw new KissoException(" Encrypt not for null."); 71 | } 72 | return KissoHelper.checkIp(request, cacheToken(request, encrypt, cache)); 73 | } 74 | 75 | /** 76 | * Token 是否缓存至 session处理逻辑 77 | *

78 | * @param request 79 | * @param encrypt 80 | * 对称加密算法类 81 | * @return Token 82 | */ 83 | private static Token cacheToken(HttpServletRequest request, Encrypt encrypt, TokenCache cache) { 84 | Token token = null; 85 | /** 86 | * 判断 Token 是否缓存至 Map 87 | * 减少Cookie解密耗时 88 | */ 89 | if (SSOConfig.getCookieCache() && cache != null) { 90 | token = cache.get(hashCookie(request)); 91 | } 92 | 93 | /** 94 | * Token 为 null 95 | * 执行以下逻辑 96 | */ 97 | if (token == null) { 98 | String jsonToken = KissoHelper.getJsonToken(request, encrypt, SSOConfig.getCookieName()); 99 | if (jsonToken == null || "".equals(jsonToken)) { 100 | /** 101 | * 未登录请求 102 | */ 103 | logger.info("jsonToken is null."); 104 | return null; 105 | } else { 106 | token = ReflectUtil.getConfigToken(); 107 | token = token.parseToken(jsonToken); 108 | 109 | /** 110 | * 判断 Token 是否缓存至 session 111 | * 减少解密次数、提高访问速度 112 | */ 113 | if (SSOConfig.getCookieCache() && cache != null) { 114 | cache.set(hashCookie(request), token); 115 | } 116 | } 117 | } 118 | return token; 119 | } 120 | 121 | /** 122 | * 退出当前登录状态 123 | *

124 | * @param request 125 | * @param response 126 | * @return boolean

true 成功, false 失败

127 | */ 128 | public static boolean logout(HttpServletRequest request, HttpServletResponse response) { 129 | return logout(request, response, ReflectUtil.getConfigTokenCache()); 130 | } 131 | 132 | /** 133 | * 退出当前登录状态 134 | *

135 | * @param request 136 | * @param response 137 | * @param TokenCache 138 | * @return boolean

true 成功, false 失败

139 | */ 140 | private static boolean logout(HttpServletRequest request, HttpServletResponse response, TokenCache cache) { 141 | if (cache == null) { 142 | throw new KissoException(" TokenCache not for null."); 143 | } 144 | /** 145 | * Token 如果开启了session缓存 146 | * 删除缓存记录 147 | */ 148 | if (SSOConfig.getCookieCache()) { 149 | cache.delete(hashCookie(request)); 150 | } 151 | /** 152 | * 删除登录 Cookie 153 | */ 154 | return CookieHelper.clearCookieByName(request, response, SSOConfig.getCookieName(), 155 | SSOConfig.getCookieDomain(), SSOConfig.getCookiePath()); 156 | } 157 | 158 | /** 159 | * 重新登录 160 | *

161 | * 退出当前登录状态、重定向至登录页. 162 | * @param request 163 | * @param response 164 | */ 165 | public static void loginAgain(HttpServletRequest request, HttpServletResponse response) throws IOException { 166 | //logout 167 | logout(request, response); 168 | String retUrl = HttpUtil.getQueryString(request, SSOConfig.getEncoding()); 169 | logger.debug("loginAgain redirect pageUrl.." + retUrl); 170 | 171 | //redirect login page 172 | response.sendRedirect(HttpUtil.encodeRetURL(SSOConfig.getLoginUrl(), "ReturnURL", retUrl)); 173 | } 174 | 175 | /** 176 | * Cookie加密值 Hash 177 | *

178 | * @param request 179 | * @return String 180 | */ 181 | public static String hashCookie(HttpServletRequest request) { 182 | Cookie uid = CookieHelper.findCookieByName(request, SSOConfig.getCookieName()); 183 | if (uid != null) { 184 | /** 185 | * MD5 会重复处理不采用 186 | * 直接返回Cookie加密内容为key 187 | */ 188 | return uid.getValue(); 189 | } 190 | return null; 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/common/Browser.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso.common; 17 | 18 | import javax.servlet.http.HttpServletRequest; 19 | 20 | import nl.bitwalker.useragentutils.UserAgent; 21 | 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | 25 | import com.github.tuzip.sso.common.encrypt.MD5; 26 | 27 | /** 28 | * 验证浏览器基本信息 29 | *

30 | * @author hubin 31 | * @Date 2014-5-8 32 | */ 33 | public class Browser { 34 | private final static Logger logger = LoggerFactory.getLogger(Browser.class); 35 | 36 | /** 37 | * @Description 获取浏览器客户端信息签名值 38 | * @param request 39 | * @return 40 | */ 41 | public static String getUserAgent(HttpServletRequest request, String value) { 42 | StringBuffer sf = new StringBuffer(); 43 | sf.append(value); 44 | sf.append("-"); 45 | /** 46 | * 混淆浏览器版本信息 47 | */ 48 | UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("user-agent")); 49 | sf.append(userAgent.getBrowser()); 50 | sf.append("-"); 51 | sf.append(userAgent.getBrowserVersion()); 52 | 53 | /** 54 | * MD5 浏览器版本信息 55 | */ 56 | return MD5.toMD5(sf.toString()); 57 | } 58 | 59 | /** 60 | * @Description 请求浏览器是否合法 61 | * (只校验客户端信息不校验domain) 62 | * @param request 63 | * @param userAgent 64 | * 浏览器客户端信息 65 | * @return 66 | */ 67 | public static boolean isLegalUserAgent(HttpServletRequest request, String value, String userAgent) { 68 | String rlt = getUserAgent(request, value); 69 | logger.debug("Browser getUserAgent:{}", rlt); 70 | 71 | if (rlt.equalsIgnoreCase(userAgent)) { 72 | logger.debug("Browser isLegalUserAgent is legal."); 73 | return true; 74 | } 75 | 76 | logger.debug("Browser isLegalUserAgent is illegal."); 77 | return false; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/common/CookieHelper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso.common; 17 | 18 | import javax.servlet.http.Cookie; 19 | import javax.servlet.http.HttpServletRequest; 20 | import javax.servlet.http.HttpServletResponse; 21 | 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | 25 | import com.github.tuzip.sso.SSOConstant; 26 | 27 | /** 28 | * Cookie工具类 29 | * 注意:在cookie的名或值中不能使用分号(;)、逗号(,)、等号(=)以及空格 30 | *

31 | * @author hubin 32 | * @Date 2014-5-8 33 | */ 34 | public class CookieHelper { 35 | private final static Logger logger = LoggerFactory.getLogger(CookieHelper.class); 36 | public final static int CLEAR_BROWSER_IS_CLOSED = -1;//浏览器关闭时自动删除 37 | public final static int CLEAR_IMMEDIATELY_REMOVE = 0;//立即删除 38 | 39 | /** 40 | * @Description 防止伪造SESSIONID攻击. 41 | * 用户登录校验成功销毁当前JSESSIONID. 42 | * 创建可信的JSESSIONID 43 | * @param request 44 | * 当前HTTP请求 45 | * @param value 46 | * 用户ID等唯一信息 47 | */ 48 | public static void authJSESSIONID(HttpServletRequest request, String value) { 49 | request.getSession().invalidate(); 50 | request.getSession().setAttribute("KISSO-" + value, true); 51 | } 52 | 53 | /** 54 | * @Description 根据cookieName获取Cookie 55 | * @param request 56 | * @param cookieName 57 | * Cookie name 58 | * @return Cookie 59 | */ 60 | public static Cookie findCookieByName(HttpServletRequest request, String cookieName) { 61 | Cookie[] cookies = request.getCookies(); 62 | if (cookies == null) 63 | return null; 64 | for (int i = 0; i < cookies.length; i++) { 65 | if (cookies[i].getName().equals(cookieName)) { 66 | return cookies[i]; 67 | } 68 | } 69 | return null; 70 | } 71 | 72 | /** 73 | * 根据 cookieName 清空 Cookie【默认域下】 74 | * @param response 75 | * @param cookieName 76 | */ 77 | public static void clearCookieByName(HttpServletResponse response, String cookieName){ 78 | Cookie cookie = new Cookie(cookieName, ""); 79 | cookie.setMaxAge(CLEAR_IMMEDIATELY_REMOVE); 80 | response.addCookie(cookie); 81 | } 82 | 83 | /** 84 | * @Description 清除指定doamin的所有Cookie 85 | * @param request 86 | * @param response 87 | * @param cookieName 88 | * cookie name 89 | * @param domain 90 | * Cookie所在的域 91 | * @param path 92 | * Cookie 路径 93 | * @return 94 | */ 95 | public static void clearAllCookie(HttpServletRequest request, HttpServletResponse response, String domain, 96 | String path) { 97 | Cookie[] cookies = request.getCookies(); 98 | for (int i = 0; i < cookies.length; i++) { 99 | clearCookie(response, cookies[i].getName(), domain, path); 100 | } 101 | logger.info("clearAllCookie in domain " + domain); 102 | } 103 | 104 | /** 105 | * @Description 根据cookieName清除指定Cookie 106 | * @param request 107 | * @param response 108 | * @param cookieName 109 | * cookie name 110 | * @param domain 111 | * Cookie所在的域 112 | * @param path 113 | * Cookie 路径 114 | * @return boolean 115 | */ 116 | public static boolean clearCookieByName(HttpServletRequest request, HttpServletResponse response, 117 | String cookieName, String domain, String path) { 118 | boolean result = false; 119 | Cookie ck = findCookieByName(request, cookieName); 120 | if (ck != null) { 121 | result = clearCookie(response, cookieName, domain, path); 122 | } 123 | return result; 124 | } 125 | 126 | /** 127 | * @Description 清除指定Cookie 等同于 clearCookieByName(...) 128 | * 该方法不判断Cookie是否存在,因此不对外暴露防止Cookie不存在异常. 129 | * @param response 130 | * @param cookieName 131 | * cookie name 132 | * @param domain 133 | * Cookie所在的域 134 | * @param path 135 | * Cookie 路径 136 | * @return boolean 137 | */ 138 | private static boolean clearCookie(HttpServletResponse response, String cookieName, 139 | String domain, String path) { 140 | boolean result = false; 141 | try { 142 | Cookie cookie = new Cookie(cookieName, ""); 143 | cookie.setMaxAge(CLEAR_IMMEDIATELY_REMOVE); 144 | cookie.setDomain(domain); 145 | cookie.setPath(path); 146 | response.addCookie(cookie); 147 | logger.info("clear cookie" + cookieName); 148 | result = true; 149 | } catch (Exception e) { 150 | logger.error("clear cookie" + cookieName + " is exception!", e); 151 | } 152 | return result; 153 | } 154 | 155 | /** 156 | * 当前域下添加 Cookie 关闭浏览器失效 157 | *

158 | * @param response 159 | * @param name 160 | * 名称 161 | * @param value 162 | * 内容 163 | */ 164 | public static void addCookie(HttpServletResponse response, String name, String value) { 165 | addCookie(response, null, name, value); 166 | } 167 | 168 | /** 169 | * 添加 Cookie 关闭浏览器失效 170 | *

171 | * @param response 172 | * @param domain 173 | * 所在域 174 | * @param name 175 | * 名称 176 | * @param value 177 | * 内容 178 | */ 179 | public static void addCookie(HttpServletResponse response, String domain, String name, String value) { 180 | addCookie(response, domain, SSOConstant.SSO_COOKIE_PATH, name, value, CLEAR_BROWSER_IS_CLOSED, false, false); 181 | } 182 | 183 | /** 184 | * 添加 Cookie 185 | *

186 | * @param response 187 | * @param domain 188 | * 所在域 189 | * @param path 190 | * 域名路径 191 | * @param name 192 | * 名称 193 | * @param value 194 | * 内容 195 | * @param maxAge 196 | * 生命周期参数 197 | * @param httpOnly 198 | * 只读 199 | * @param secured 200 | * Https协议下安全传输 201 | */ 202 | public static void addCookie(HttpServletResponse response, String domain, String path, String name, String value, 203 | int maxAge, boolean httpOnly, boolean secured) { 204 | Cookie cookie = new Cookie(name, value); 205 | /** 206 | * 不设置该参数默认 207 | * 当前所在域 208 | */ 209 | if (domain != null && !"".equals(domain)) { 210 | cookie.setDomain(domain); 211 | } 212 | cookie.setPath(path); 213 | cookie.setMaxAge(maxAge); 214 | 215 | /** Cookie 只在Https协议下传输设置 */ 216 | if (secured) { 217 | cookie.setSecure(secured); 218 | } 219 | 220 | /** Cookie 只读设置 */ 221 | if (httpOnly) { 222 | addHttpOnlyCookie(response, cookie); 223 | } else { 224 | //cookie.setHttpOnly(httpOnly);//servlet 3.0 support 225 | response.addCookie(cookie); 226 | } 227 | 228 | } 229 | 230 | /** 231 | * 解决 servlet 3.0 以下版本不支持 HttpOnly 232 | *

233 | * @param response HttpServletResponse类型的响应 234 | * @param cookie 要设置httpOnly的cookie对象 235 | */ 236 | public static void addHttpOnlyCookie(HttpServletResponse response, Cookie cookie) { 237 | if (cookie == null) { 238 | return; 239 | } 240 | /** 241 | * 依次取得cookie中的名称、值、 242 | * 最大生存时间、路径、域和是否为安全协议信息 243 | */ 244 | String cookieName = cookie.getName(); 245 | String cookieValue = cookie.getValue(); 246 | int maxAge = cookie.getMaxAge(); 247 | String path = cookie.getPath(); 248 | String domain = cookie.getDomain(); 249 | boolean isSecure = cookie.getSecure(); 250 | StringBuffer sf = new StringBuffer(); 251 | sf.append(cookieName + "=" + cookieValue + ";"); 252 | 253 | if (maxAge >= 0) { 254 | sf.append("Max-Age=" + cookie.getMaxAge() + ";"); 255 | } 256 | 257 | if (domain != null) { 258 | sf.append("domain=" + domain + ";"); 259 | } 260 | 261 | if (path != null) { 262 | sf.append("path=" + path + ";"); 263 | } 264 | 265 | if (isSecure) { 266 | sf.append("secure;HTTPOnly;"); 267 | } else { 268 | sf.append("HTTPOnly;"); 269 | } 270 | 271 | response.addHeader("Set-Cookie", sf.toString()); 272 | } 273 | 274 | } 275 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/common/FileHashHelper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso.common; 17 | 18 | import java.io.File; 19 | import java.io.FileInputStream; 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | import java.security.MessageDigest; 23 | import java.security.NoSuchAlgorithmException; 24 | import java.security.Provider; 25 | import java.security.Security; 26 | import java.util.HashSet; 27 | import java.util.Iterator; 28 | import java.util.Set; 29 | 30 | import org.slf4j.Logger; 31 | import org.slf4j.LoggerFactory; 32 | 33 | import com.github.tuzip.sso.common.encrypt.MD5; 34 | 35 | 36 | /** 37 | * 文件 Hash 帮助类 38 | *

39 | * @author hubin 40 | * @Date 2014-8-11 41 | */ 42 | public class FileHashHelper { 43 | private final static Logger logger = LoggerFactory.getLogger(FileHashHelper.class); 44 | 45 | /** 46 | * 获取文件文件MD5 Hash值 47 | *

48 | * @param pathName 49 | * 文件绝对地址 50 | * @return 51 | * @throws NoSuchAlgorithmException 52 | * @throws IOException 53 | */ 54 | public static String getMD5Hash(String fileName) throws NoSuchAlgorithmException, IOException{ 55 | return getHash(fileName, "MD5"); 56 | } 57 | 58 | /** 59 | * 获取文件文件MD5 Hash值 60 | *

61 | * @param InputStream 62 | * 文件输入流 63 | * @return 64 | * @throws IOException 65 | * @throws NoSuchAlgorithmException 66 | */ 67 | public static String getMD5Hash(InputStream ins) throws NoSuchAlgorithmException, IOException{ 68 | return getHash(ins, "MD5"); 69 | } 70 | 71 | /** 72 | * 获取文件文件Hash值 73 | *

74 | * @param pathName 75 | * 文件绝对地址 76 | * @param hashType 77 | * MessageDigest 加密算法 78 | * @return 79 | * @throws IOException 80 | * @throws NoSuchAlgorithmException 81 | */ 82 | public static String getHash(String pathName, String hashType) throws IOException, NoSuchAlgorithmException { 83 | File f = new File(pathName); 84 | logger.debug(" -------------------------------------------------------------------------------"); 85 | logger.debug("|当前文件名称:" + f.getName()); 86 | logger.debug("|当前文件大小:" + (f.length() / 1024 / 1024) + "MB"); 87 | logger.debug("|当前文件路径[绝对]:" + f.getAbsolutePath()); 88 | logger.debug("|当前文件路径[---]:" + f.getCanonicalPath()); 89 | logger.debug("|当前文件最后一次被修改时间[---]:" + f.lastModified()); 90 | logger.debug(" -------------------------------------------------------------------------------"); 91 | return getHash(new FileInputStream(f), hashType); 92 | } 93 | 94 | /** 95 | * 获取文件文件Hash值 96 | *

97 | * @param InputStream 98 | * 文件输入流 99 | * @param hashType 100 | * MessageDigest 加密算法 101 | * @return 102 | * @throws IOException 103 | * @throws NoSuchAlgorithmException 104 | */ 105 | public static String getHash(InputStream ins, String hashType) throws IOException, NoSuchAlgorithmException { 106 | if(ins == null){ 107 | //输入流为空返回 null 108 | return null; 109 | } 110 | byte[] buffer = new byte[8192]; 111 | MessageDigest md5 = MessageDigest.getInstance(hashType); 112 | int len; 113 | while ((len = ins.read(buffer)) != -1) { 114 | md5.update(buffer, 0, len); 115 | } 116 | ins.close(); 117 | return MD5.byte2Hex(md5.digest()); 118 | } 119 | 120 | /** 121 | * 获取MessageDigest支持几种加密算法 122 | * SHA-256 SHA-512 SHA SHA-384 SHA1 MD5 SHA-1 MD2 123 | */ 124 | @SuppressWarnings({ "rawtypes", "unchecked"}) 125 | private static String[] getCryptolmpls(String serviceType) { 126 | Set result = new HashSet(); 127 | //all providers 128 | Provider[] providers = Security.getProviders(); 129 | for (int i = 0; i < providers.length; i++) { 130 | //get services provided by each provider 131 | Set keys = providers[i].keySet(); 132 | for (Iterator it = keys.iterator(); it.hasNext();) { 133 | String key = it.next().toString(); 134 | key = key.split(" ")[0]; 135 | if (key.startsWith(serviceType + ".")) { 136 | result.add(key.substring(serviceType.length() + 1)); 137 | } else if (key.startsWith("Alg.Alias." + serviceType + ".")) { 138 | result.add(key.substring(serviceType.length() + 11)); 139 | } 140 | } 141 | } 142 | return (String[]) result.toArray(new String[result.size()]); 143 | } 144 | 145 | /** 146 | * 测试 147 | */ 148 | public static void main(String[] args) throws Exception { 149 | //MessageDigest 支持的加密算法 150 | String[] names = getCryptolmpls("MessageDigest"); 151 | System.out.println("MessageDigest 支持的加密算法: "); 152 | for(String name:names){ 153 | System.out.println(name); 154 | } 155 | 156 | long start = System.currentTimeMillis(); 157 | System.out.println("开始计算文件MD5值,请稍后..."); 158 | System.out.println("MD5:" + getMD5Hash("E:/Office_Visio_Pro_2007.iso")); 159 | long end = System.currentTimeMillis(); 160 | System.out.println("一共耗时:" + (end - start) + "毫秒"); 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/common/IpHelper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso.common; 17 | 18 | import java.net.InetAddress; 19 | import java.net.UnknownHostException; 20 | 21 | import javax.servlet.http.HttpServletRequest; 22 | 23 | /** 24 | * 获取IP地址类 25 | *

26 | * @author hubin 27 | * @Date 2014-5-8 28 | */ 29 | public class IpHelper { 30 | 31 | private static String LOCAL_IP_STAR_STR = "192.168."; 32 | 33 | static { 34 | String ip = null; 35 | String hostName = null; 36 | try { 37 | hostName = InetAddress.getLocalHost().getHostName(); 38 | InetAddress ipAddr[] = InetAddress.getAllByName(hostName); 39 | for (int i = 0; i < ipAddr.length; i++) { 40 | ip = ipAddr[i].getHostAddress(); 41 | if (ip.startsWith(LOCAL_IP_STAR_STR)) { 42 | break; 43 | } 44 | } 45 | if (ip == null) { 46 | ip = ipAddr[0].getHostAddress(); 47 | } 48 | 49 | } catch (UnknownHostException e) { 50 | e.printStackTrace(); 51 | } 52 | 53 | LOCAL_IP = ip; 54 | HOST_NAME = hostName; 55 | 56 | } 57 | 58 | /** 系统的本地IP地址 */ 59 | public static final String LOCAL_IP; 60 | 61 | /** 系统的本地服务器名 */ 62 | public static final String HOST_NAME; 63 | 64 | /** 65 | * @Description 获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的。 66 | * 但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实IP地址了,如果通过了多级反向代理的话, 67 | * X-Forwarded-For的值并不止一个,而是一串IP值, 究竟哪个才是真正的用户端的真实IP呢? 68 | * 答案是取X-Forwarded-For中第一个非unknown的有效IP字符串。 69 | * 例如:X-Forwarded-For:192.168.1.110, 192.168.1.120, 192.168.1.130, 192.168.1.100 70 | * 用户真实IP为: 192.168.1.110 71 | * @param request 72 | * @return 73 | */ 74 | public static String getIpAddr(HttpServletRequest request) { 75 | String ip = request.getHeader("x-forwarded-for"); 76 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 77 | ip = request.getHeader("Proxy-Client-IP"); 78 | } 79 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 80 | ip = request.getHeader("WL-Proxy-Client-IP"); 81 | } 82 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 83 | ip = request.getRemoteAddr(); 84 | if (ip.equals("127.0.0.1")) { 85 | /** 根据网卡取本机配置的IP */ 86 | InetAddress inet = null; 87 | try { 88 | inet = InetAddress.getLocalHost(); 89 | ip = inet.getHostAddress(); 90 | } catch (UnknownHostException e) { 91 | e.printStackTrace(); 92 | } 93 | } 94 | } 95 | /** 96 | * 对于通过多个代理的情况, 97 | * 第一个IP为客户端真实IP,多个IP按照','分割 98 | * "***.***.***.***".length() = 15 99 | */ 100 | if (ip != null && ip.length() > 15) { 101 | if (ip.indexOf(",") > 0) { 102 | ip = ip.substring(0, ip.indexOf(",")); 103 | } 104 | } 105 | return ip; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/common/encrypt/AES.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso.common.encrypt; 17 | 18 | import javax.crypto.Cipher; 19 | import javax.crypto.SecretKey; 20 | import javax.crypto.spec.SecretKeySpec; 21 | 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | 25 | import com.github.tuzip.sso.SSOConfig; 26 | import com.github.tuzip.sso.common.util.Base64Util; 27 | 28 | /** 29 | * AES encrypt util 30 | *

31 | * @author hubin 32 | * @Date 2014-5-8 33 | */ 34 | public class AES extends Encrypt { 35 | private static final Logger LOGGER = LoggerFactory.getLogger(AES.class); 36 | private static final String ALGORITHM = "AES"; 37 | SecretKeySpec secretKey; 38 | 39 | public AES() { 40 | setKey(SSOConfig.getSecretKey());//secret key 41 | } 42 | 43 | public AES(String str) { 44 | setKey(str);//generate secret key 45 | } 46 | 47 | public SecretKey getSecretKey() { 48 | return secretKey; 49 | } 50 | 51 | /** 52 | * generate KEY 53 | */ 54 | public void setKey(String strKey) { 55 | try { 56 | byte[] bk = MD5.md5Raw(strKey.getBytes(SSOConfig.getEncoding())); 57 | this.secretKey = new SecretKeySpec(bk, ALGORITHM); 58 | } catch (Exception e) { 59 | LOGGER.error("Encrypt setKey is exception:", e.getMessage()); 60 | } 61 | } 62 | 63 | /** 64 | * @Description AES encrypt 65 | * @param str 66 | * @return 67 | */ 68 | public String encryptAES(String str) { 69 | byte[] encryptBytes = null; 70 | String encryptStr = null; 71 | try { 72 | Cipher cipher = Cipher.getInstance(ALGORITHM); 73 | cipher.init(Cipher.ENCRYPT_MODE, getSecretKey()); 74 | encryptBytes = cipher.doFinal(str.getBytes()); 75 | if (encryptBytes != null) { 76 | encryptStr = Base64Util.encryptBASE64(encryptBytes); 77 | } 78 | } catch (Exception e) { 79 | LOGGER.error("Encrypt encryptAES is exception:", e.getMessage()); 80 | } 81 | return encryptStr; 82 | } 83 | 84 | /** 85 | * @Description AES decrypt 86 | * @param str 87 | * @return 88 | */ 89 | public String decryptAES(String str) { 90 | byte[] decryptBytes = null; 91 | String decryptStr = null; 92 | try { 93 | Cipher cipher = Cipher.getInstance(ALGORITHM); 94 | cipher.init(Cipher.DECRYPT_MODE, getSecretKey()); 95 | byte[] scrBytes = Base64Util.decryptBASE64(str); 96 | decryptBytes = cipher.doFinal(scrBytes); 97 | } catch (Exception e) { 98 | LOGGER.error("Encrypt decryptAES is exception:", e.getMessage()); 99 | } 100 | if (decryptBytes != null) { 101 | decryptStr = new String(decryptBytes); 102 | } 103 | return decryptStr; 104 | } 105 | 106 | /** 107 | * AES encrypt 108 | */ 109 | @Override 110 | public String encrypt(String value, String key) throws Exception { 111 | return this.encryptAES(value); 112 | } 113 | 114 | /** 115 | * AES decrypt 116 | */ 117 | @Override 118 | public String decrypt(String value, String key) throws Exception { 119 | return this.decryptAES(value); 120 | 121 | } 122 | 123 | /** 124 | * test 125 | */ 126 | public static void main(String[] args) { 127 | String password = "100010\n1w#E#测试\nssAASASSC\n127.0.0.1\nlif123gsjkdsgvjxeh\n"; 128 | AES en = new AES("lifgnfdfg216958134gsjkdsgvjxeh"); 129 | String encryptPwd = en.encryptAES(password); 130 | System.out.println(encryptPwd); 131 | String decryptPwd = en.decryptAES(encryptPwd); 132 | System.out.println(decryptPwd); 133 | } 134 | } -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/common/encrypt/Encrypt.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso.common.encrypt; 17 | 18 | /** 19 | * SSO 对称加密父类 20 | *

21 | * @author hubin 22 | * @Date 2014-5-9 23 | */ 24 | public abstract class Encrypt { 25 | 26 | /** 27 | * 字符串内容加密 28 | *

29 | * @param value 加密内容 30 | * @param key 密钥 31 | * @return 32 | * @throws Exception 33 | */ 34 | public abstract String encrypt(String value, String key) throws Exception; 35 | 36 | /** 37 | * 字符串内容解密 38 | *

39 | * @param value 解密内容 40 | * @param key 密钥 41 | * @return 42 | * @throws Exception 43 | */ 44 | public abstract String decrypt(String value, String key) throws Exception; 45 | } 46 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/common/encrypt/MD5.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso.common.encrypt; 17 | 18 | import java.io.IOException; 19 | import java.io.UnsupportedEncodingException; 20 | import java.security.MessageDigest; 21 | import java.util.Formatter; 22 | import java.util.HashMap; 23 | import java.util.Map; 24 | import java.util.Map.Entry; 25 | import java.util.Set; 26 | import java.util.TreeMap; 27 | 28 | import org.slf4j.Logger; 29 | import org.slf4j.LoggerFactory; 30 | 31 | import com.github.tuzip.sso.SSOConfig; 32 | 33 | /** 34 | * MD5加密工具类 35 | *

36 | * @author hubin 37 | * @Date 2014-5-9 38 | */ 39 | public class MD5 { 40 | private final static Logger logger = LoggerFactory.getLogger(MD5.class); 41 | 42 | /** 43 | * @Description 字符串加密为MD5 44 | * 中文加密一致通用,必须转码处理: 45 | * plainText.getBytes("UTF-8") 46 | * @param plainText 47 | * 需要加密的字符串 48 | * @return 49 | */ 50 | public static String toMD5(String plainText) { 51 | StringBuffer rlt = new StringBuffer(); 52 | try { 53 | rlt.append(md5String(plainText.getBytes(SSOConfig.getEncoding()))); 54 | } catch (UnsupportedEncodingException e) { 55 | logger.error(" CipherHelper toMD5 exception:", e.toString()); 56 | } 57 | return rlt.toString(); 58 | } 59 | 60 | /** 61 | * MD5 参数签名生成算法 62 | * @param HashMap params 请求参数集,所有参数必须已转换为字符串类型 63 | * @param String secret 签名密钥 64 | * @return 签名 65 | * @throws IOException 66 | */ 67 | public static String getSignature(HashMap params, String secret) throws IOException { 68 | Map sortedParams = new TreeMap(params); 69 | Set> entrys = sortedParams.entrySet(); 70 | StringBuilder basestring = new StringBuilder(); 71 | for (Entry param : entrys) { 72 | basestring.append(param.getKey()).append("=").append(param.getValue()); 73 | } 74 | basestring.append(secret); 75 | byte[] bytes = md5Raw(basestring.toString().getBytes(SSOConfig.getEncoding())); 76 | StringBuilder sign = new StringBuilder(); 77 | for (int i = 0; i < bytes.length; i++) { 78 | String hex = Integer.toHexString(bytes[i] & 0xFF); 79 | if (hex.length() == 1) { 80 | sign.append("0"); 81 | } 82 | sign.append(hex); 83 | } 84 | return sign.toString(); 85 | } 86 | 87 | public static byte[] md5Raw(byte[] data) { 88 | byte[] md5buf = null; 89 | try { 90 | MessageDigest md5 = MessageDigest.getInstance("md5"); 91 | md5buf = md5.digest(data); 92 | } catch (Exception e) { 93 | md5buf = null; 94 | e.printStackTrace(System.err); 95 | } 96 | return md5buf; 97 | } 98 | 99 | public static String md5String(byte[] data) { 100 | String md5Str = null; 101 | try { 102 | MessageDigest md5 = MessageDigest.getInstance("md5"); 103 | md5Str = ""; 104 | byte[] buf = md5.digest(data); 105 | for (int i = 0; i < buf.length; i++) { 106 | md5Str += byte2Hex(buf[i]); 107 | } 108 | } catch (Exception e) { 109 | md5Str = null; 110 | e.printStackTrace(System.err); 111 | } 112 | return md5Str; 113 | } 114 | 115 | public static String byte2Hex(byte b) { 116 | String hex = Integer.toHexString(b); 117 | if (hex.length() > 2) { 118 | hex = hex.substring(hex.length() - 2); 119 | } 120 | while (hex.length() < 2) { 121 | hex = "0" + hex; 122 | } 123 | return hex; 124 | } 125 | 126 | public static String byte2Hex(byte[] bytes) { 127 | Formatter formatter = new Formatter(); 128 | for (byte b : bytes) { 129 | formatter.format("%02x", b); 130 | } 131 | String hash = formatter.toString(); 132 | formatter.close(); 133 | return hash; 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/common/encrypt/RSA.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso.common.encrypt; 17 | 18 | import java.io.ByteArrayOutputStream; 19 | import java.security.Key; 20 | import java.security.KeyFactory; 21 | import java.security.KeyPair; 22 | import java.security.KeyPairGenerator; 23 | import java.security.PrivateKey; 24 | import java.security.PublicKey; 25 | import java.security.Signature; 26 | import java.security.interfaces.RSAPrivateKey; 27 | import java.security.interfaces.RSAPublicKey; 28 | import java.security.spec.PKCS8EncodedKeySpec; 29 | import java.security.spec.X509EncodedKeySpec; 30 | import java.util.HashMap; 31 | import java.util.Map; 32 | 33 | import javax.crypto.Cipher; 34 | 35 | import com.github.tuzip.sso.common.util.Base64Util; 36 | 37 | /** 38 | *

39 | * RSA公钥/私钥/签名工具包 40 | *

41 | *

42 | * 罗纳德·李维斯特(Ron [R]ivest)、阿迪·萨莫尔(Adi [S]hamir)和伦纳德·阿德曼(Leonard [A]dleman) 43 | *

44 | *

45 | * 字符串格式的密钥在未在特殊说明情况下都为BASE64编码格式
46 | * 由于非对称加密速度极其缓慢,一般文件不使用它来加密而是使用对称加密,
47 | * 非对称加密算法可以用来对对称加密的密钥加密,这样保证密钥的安全也就保证了数据的安全 48 | *

49 | * @author hubin 50 | * @Date 2014-6-17 51 | */ 52 | public class RSA { 53 | 54 | /** 55 | * 加密算法RSA 56 | */ 57 | public static final String KEY_ALGORITHM = "RSA"; 58 | 59 | /** 60 | * 签名算法 61 | */ 62 | public static final String SIGNATURE_ALGORITHM = "MD5withRSA"; 63 | 64 | /** 65 | * 获取公钥的key 66 | */ 67 | private static final String PUBLIC_KEY = "RSAPublicKey"; 68 | 69 | /** 70 | * 获取私钥的key 71 | */ 72 | private static final String PRIVATE_KEY = "RSAPrivateKey"; 73 | 74 | /** 75 | * RSA最大加密明文大小 76 | */ 77 | private static final int MAX_ENCRYPT_BLOCK = 117; 78 | 79 | /** 80 | * RSA最大解密密文大小 81 | */ 82 | private static final int MAX_DECRYPT_BLOCK = 128; 83 | 84 | /** 85 | *

86 | * 生成密钥对(公钥和私钥) 87 | *

88 | * 89 | * @return 90 | * @throws Exception 91 | */ 92 | public static Map genKeyPair() throws Exception { 93 | KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM); 94 | keyPairGen.initialize(1024); 95 | KeyPair keyPair = keyPairGen.generateKeyPair(); 96 | RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); 97 | RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); 98 | Map keyMap = new HashMap(2); 99 | keyMap.put(PUBLIC_KEY, publicKey); 100 | keyMap.put(PRIVATE_KEY, privateKey); 101 | return keyMap; 102 | } 103 | 104 | /** 105 | *

106 | * 用私钥对信息生成数字签名 107 | *

108 | * 109 | * @param data 已加密数据 110 | * @param privateKey 私钥(BASE64编码) 111 | * 112 | * @return 113 | * @throws Exception 114 | */ 115 | public static String sign(byte[] data, String privateKey) throws Exception { 116 | byte[] keyBytes = Base64Util.decode(privateKey); 117 | PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); 118 | KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 119 | PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec); 120 | Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); 121 | signature.initSign(privateK); 122 | signature.update(data); 123 | return Base64Util.encode(signature.sign()); 124 | } 125 | 126 | /** 127 | *

128 | * 校验数字签名 129 | *

130 | * 131 | * @param data 已加密数据 132 | * @param publicKey 公钥(BASE64编码) 133 | * @param sign 数字签名 134 | * 135 | * @return 136 | * @throws Exception 137 | * 138 | */ 139 | public static boolean verify(byte[] data, String publicKey, String sign) throws Exception { 140 | byte[] keyBytes = Base64Util.decode(publicKey); 141 | X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); 142 | KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 143 | PublicKey publicK = keyFactory.generatePublic(keySpec); 144 | Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); 145 | signature.initVerify(publicK); 146 | signature.update(data); 147 | return signature.verify(Base64Util.decode(sign)); 148 | } 149 | 150 | /** 151 | *

152 | * 私钥解密 153 | *

154 | * 155 | * @param encryptedData 已加密数据 156 | * @param privateKey 私钥(BASE64编码) 157 | * @return 158 | * @throws Exception 159 | */ 160 | public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) throws Exception { 161 | byte[] keyBytes = Base64Util.decode(privateKey); 162 | PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); 163 | KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 164 | Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); 165 | Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); 166 | cipher.init(Cipher.DECRYPT_MODE, privateK); 167 | int inputLen = encryptedData.length; 168 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 169 | int offSet = 0; 170 | byte[] cache; 171 | int i = 0; 172 | // 对数据分段解密 173 | while (inputLen - offSet > 0) { 174 | if (inputLen - offSet > MAX_DECRYPT_BLOCK) { 175 | cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK); 176 | } else { 177 | cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet); 178 | } 179 | out.write(cache, 0, cache.length); 180 | i++; 181 | offSet = i * MAX_DECRYPT_BLOCK; 182 | } 183 | byte[] decryptedData = out.toByteArray(); 184 | out.close(); 185 | return decryptedData; 186 | } 187 | 188 | /** 189 | *

190 | * 公钥解密 191 | *

192 | * 193 | * @param encryptedData 已加密数据 194 | * @param publicKey 公钥(BASE64编码) 195 | * @return 196 | * @throws Exception 197 | */ 198 | public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey) throws Exception { 199 | byte[] keyBytes = Base64Util.decode(publicKey); 200 | X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); 201 | KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 202 | Key publicK = keyFactory.generatePublic(x509KeySpec); 203 | Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); 204 | cipher.init(Cipher.DECRYPT_MODE, publicK); 205 | int inputLen = encryptedData.length; 206 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 207 | int offSet = 0; 208 | byte[] cache; 209 | int i = 0; 210 | // 对数据分段解密 211 | while (inputLen - offSet > 0) { 212 | if (inputLen - offSet > MAX_DECRYPT_BLOCK) { 213 | cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK); 214 | } else { 215 | cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet); 216 | } 217 | out.write(cache, 0, cache.length); 218 | i++; 219 | offSet = i * MAX_DECRYPT_BLOCK; 220 | } 221 | byte[] decryptedData = out.toByteArray(); 222 | out.close(); 223 | return decryptedData; 224 | } 225 | 226 | /** 227 | *

228 | * 公钥加密 229 | *

230 | * 231 | * @param data 源数据 232 | * @param publicKey 公钥(BASE64编码) 233 | * @return 234 | * @throws Exception 235 | */ 236 | public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception { 237 | byte[] keyBytes = Base64Util.decode(publicKey); 238 | X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); 239 | KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 240 | Key publicK = keyFactory.generatePublic(x509KeySpec); 241 | // 对数据加密 242 | Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); 243 | cipher.init(Cipher.ENCRYPT_MODE, publicK); 244 | int inputLen = data.length; 245 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 246 | int offSet = 0; 247 | byte[] cache; 248 | int i = 0; 249 | // 对数据分段加密 250 | while (inputLen - offSet > 0) { 251 | if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { 252 | cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); 253 | } else { 254 | cache = cipher.doFinal(data, offSet, inputLen - offSet); 255 | } 256 | out.write(cache, 0, cache.length); 257 | i++; 258 | offSet = i * MAX_ENCRYPT_BLOCK; 259 | } 260 | byte[] encryptedData = out.toByteArray(); 261 | out.close(); 262 | return encryptedData; 263 | } 264 | 265 | /** 266 | *

267 | * 私钥加密 268 | *

269 | * 270 | * @param data 源数据 271 | * @param privateKey 私钥(BASE64编码) 272 | * @return 273 | * @throws Exception 274 | */ 275 | public static byte[] encryptByPrivateKey(byte[] data, String privateKey) throws Exception { 276 | byte[] keyBytes = Base64Util.decode(privateKey); 277 | PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); 278 | KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 279 | Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); 280 | Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); 281 | cipher.init(Cipher.ENCRYPT_MODE, privateK); 282 | int inputLen = data.length; 283 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 284 | int offSet = 0; 285 | byte[] cache; 286 | int i = 0; 287 | // 对数据分段加密 288 | while (inputLen - offSet > 0) { 289 | if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { 290 | cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); 291 | } else { 292 | cache = cipher.doFinal(data, offSet, inputLen - offSet); 293 | } 294 | out.write(cache, 0, cache.length); 295 | i++; 296 | offSet = i * MAX_ENCRYPT_BLOCK; 297 | } 298 | byte[] encryptedData = out.toByteArray(); 299 | out.close(); 300 | return encryptedData; 301 | } 302 | 303 | /** 304 | *

305 | * 获取私钥 306 | *

307 | * 308 | * @param keyMap 密钥对 309 | * @return 310 | * @throws Exception 311 | */ 312 | public static String getPrivateKey(Map keyMap) throws Exception { 313 | Key key = (Key) keyMap.get(PRIVATE_KEY); 314 | return Base64Util.encode(key.getEncoded()); 315 | } 316 | 317 | /** 318 | *

319 | * 获取公钥 320 | *

321 | * 322 | * @param keyMap 密钥对 323 | * @return 324 | * @throws Exception 325 | */ 326 | public static String getPublicKey(Map keyMap) throws Exception { 327 | Key key = (Key) keyMap.get(PUBLIC_KEY); 328 | return Base64Util.encode(key.getEncoded()); 329 | } 330 | 331 | } -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/common/util/Base64Util.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso.common.util; 17 | 18 | import java.io.ByteArrayInputStream; 19 | import java.io.ByteArrayOutputStream; 20 | import java.io.File; 21 | import java.io.FileInputStream; 22 | import java.io.FileOutputStream; 23 | import java.io.InputStream; 24 | import java.io.OutputStream; 25 | import java.security.Security; 26 | 27 | import org.bouncycastle.jce.provider.BouncyCastleProvider; 28 | import org.bouncycastle.util.encoders.Base64; 29 | import org.bouncycastle.util.encoders.UrlBase64; 30 | 31 | import com.github.tuzip.sso.SSOConfig; 32 | 33 | /** 34 | *

35 | * BASE64编码解码工具包 36 | *

37 | *

38 | * 依赖bcprov-jdk14-1.48.jar 39 | *

40 | *

41 | * @author hubin 42 | * @Date 2014-6-17 43 | */ 44 | public class Base64Util { 45 | 46 | /** 47 | * 文件读取缓冲区大小 48 | */ 49 | private static final int CACHE_SIZE = 1024; 50 | 51 | /** 52 | *

53 | * BASE64字符串解码为二进制数据 54 | *

55 | * 56 | * @param base64 57 | * @return 58 | * @throws Exception 59 | */ 60 | public static byte[] decode(String base64) throws Exception { 61 | return Base64.decode(base64.getBytes()); 62 | } 63 | 64 | /** 65 | *

66 | * 二进制数据编码为BASE64字符串 67 | *

68 | * 69 | * @param bytes 70 | * @return 71 | * @throws Exception 72 | */ 73 | public static String encode(byte[] bytes) throws Exception { 74 | return new String(Base64.encode(bytes)); 75 | } 76 | 77 | /** 78 | * BASE64 encrypt 79 | * 80 | * @param key 81 | * @return 82 | * @throws Exception 83 | */ 84 | public static String encryptBASE64(byte[] key) throws Exception { 85 | Security.addProvider(new BouncyCastleProvider()); 86 | byte[] b = UrlBase64.encode(key); 87 | return new String(b, SSOConfig.getEncoding()); 88 | } 89 | 90 | /** 91 | * BASE64 decrypt 92 | * 93 | * @param key 94 | * @return 95 | * @throws Exception 96 | */ 97 | public static byte[] decryptBASE64(String key) throws Exception { 98 | Security.addProvider(new BouncyCastleProvider()); 99 | return UrlBase64.decode(key.getBytes(SSOConfig.getEncoding())); 100 | } 101 | 102 | /** 103 | *

104 | * 将文件编码为BASE64字符串 105 | *

106 | *

107 | * 大文件慎用,可能会导致内存溢出 108 | *

109 | * 110 | * @param filePath 文件绝对路径 111 | * @return 112 | * @throws Exception 113 | */ 114 | public static String encodeFile(String filePath) throws Exception { 115 | byte[] bytes = fileToByte(filePath); 116 | return encode(bytes); 117 | } 118 | 119 | /** 120 | *

121 | * BASE64字符串转回文件 122 | *

123 | * 124 | * @param filePath 文件绝对路径 125 | * @param base64 编码字符串 126 | * @throws Exception 127 | */ 128 | public static void decodeToFile(String filePath, String base64) throws Exception { 129 | byte[] bytes = decode(base64); 130 | byteArrayToFile(bytes, filePath); 131 | } 132 | 133 | /** 134 | * 文件绝对路径 135 | *

136 | * @param linuxDir 137 | * linux存放目录 138 | * @param winDir 139 | * win存放目录 140 | * @param fileName 141 | * 文件名 142 | * @return String 143 | */ 144 | public static String filePath(String linuxDir, String winDir, String fileName) { 145 | StringBuffer bf = new StringBuffer(); 146 | if ("\\".equals(File.separator)) { 147 | //windows 148 | bf.append(winDir); 149 | } else if ("/".equals(File.separator)) { 150 | //Linux 151 | bf.append(linuxDir); 152 | } 153 | bf.append(File.separator); 154 | bf.append(fileName); 155 | return bf.toString(); 156 | } 157 | 158 | /** 159 | *

160 | * 文件转换为二进制数组 161 | *

162 | * 163 | * @param filePath 文件路径 164 | * @return 165 | * @throws Exception 166 | */ 167 | public static byte[] fileToByte(String filePath) throws Exception { 168 | byte[] data = new byte[0]; 169 | File file = new File(filePath); 170 | if (file.exists()) { 171 | FileInputStream in = new FileInputStream(file); 172 | ByteArrayOutputStream out = new ByteArrayOutputStream(2048); 173 | byte[] cache = new byte[CACHE_SIZE]; 174 | int nRead = 0; 175 | while ((nRead = in.read(cache)) != -1) { 176 | out.write(cache, 0, nRead); 177 | out.flush(); 178 | } 179 | out.close(); 180 | in.close(); 181 | data = out.toByteArray(); 182 | } 183 | return data; 184 | } 185 | 186 | /** 187 | *

188 | * 二进制数据写文件 189 | *

190 | * 191 | * @param bytes 二进制数据 192 | * @param filePath 文件生成目录 193 | */ 194 | public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception { 195 | InputStream in = new ByteArrayInputStream(bytes); 196 | File destFile = new File(filePath); 197 | if (!destFile.getParentFile().exists()) { 198 | destFile.getParentFile().mkdirs(); 199 | } 200 | destFile.createNewFile(); 201 | OutputStream out = new FileOutputStream(destFile); 202 | byte[] cache = new byte[CACHE_SIZE]; 203 | int nRead = 0; 204 | while ((nRead = in.read(cache)) != -1) { 205 | out.write(cache, 0, nRead); 206 | out.flush(); 207 | } 208 | out.close(); 209 | in.close(); 210 | } 211 | 212 | } 213 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/common/util/DateUtil.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso.common.util; 17 | 18 | import java.sql.Timestamp; 19 | import java.text.SimpleDateFormat; 20 | import java.util.Date; 21 | import java.util.TimeZone; 22 | 23 | /** 24 | * 日期工具类 25 | *

26 | * @author hubin 27 | * @Date 2014-5-12 28 | */ 29 | public class DateUtil { 30 | 31 | /** 32 | * @Description 获取当前中国时区的TIMESTAMP日期 33 | * @return 34 | */ 35 | public static Timestamp getSysTimestamp() { 36 | final TimeZone zone = TimeZone.getTimeZone("GMT+8");//获取中国时区 37 | TimeZone.setDefault(zone);//设置时区 38 | return new Timestamp((new java.util.Date()).getTime()); 39 | } 40 | 41 | /** 42 | * 格式日期为字符串内容 43 | *

44 | * @param date 时间 45 | * @param pattern 日期格式,例: yyyyMMddHHmmss 46 | * @return String 格式后的字符串日期 47 | */ 48 | public static String formatDate(Date date, String pattern) { 49 | SimpleDateFormat format = new SimpleDateFormat(pattern); 50 | return format.format(date); 51 | } 52 | 53 | /** 54 | * 格式long类型日期为 Date 55 | *

56 | * @param time long类型日期 57 | * @return Date 58 | */ 59 | public static Date formatDate(long time) { 60 | return new Date(time); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/common/util/HttpUtil.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso.common.util; 17 | 18 | import java.io.IOException; 19 | import java.io.UnsupportedEncodingException; 20 | import java.net.URLEncoder; 21 | 22 | import javax.servlet.http.HttpServletRequest; 23 | 24 | import com.github.tuzip.sso.SSOConfig; 25 | 26 | /** 27 | * HTTP工具类 28 | *

29 | * @author hubin 30 | * @Date 2014-5-8 31 | */ 32 | public class HttpUtil { 33 | 34 | /** 35 | * @Description 获取URL查询条件 36 | * @param request 37 | * @param encode 38 | * URLEncoder编码格式 39 | * @return 40 | * @throws IOException 41 | */ 42 | public static String getQueryString(HttpServletRequest request, String encode) throws IOException { 43 | StringBuffer sb = request.getRequestURL(); 44 | String query = request.getQueryString(); 45 | if (query != null && query.length() > 0) { 46 | sb.append("?").append(query); 47 | } 48 | return URLEncoder.encode(sb.toString(), encode); 49 | } 50 | 51 | /** 52 | * @Description getRequestURL是否包含在URL之内 53 | * @param request 54 | * @param url 55 | * 参数为以';'分割的URL字符串 56 | * @return 57 | */ 58 | public static boolean inContainURL(HttpServletRequest request, String url) { 59 | boolean result = false; 60 | if (url != null && !"".equals(url.trim())) { 61 | String[] urlArr = url.split(";"); 62 | StringBuffer reqUrl = request.getRequestURL(); 63 | for (int i = 0; i < urlArr.length; i++) { 64 | if (reqUrl.indexOf(urlArr[i]) > 1) { 65 | result = true; 66 | break; 67 | } 68 | } 69 | } 70 | return result; 71 | } 72 | 73 | /** 74 | * @Description URLEncoder返回地址 75 | * @param url 76 | * 跳转地址 77 | * @param retParam 78 | * 返回地址参数名 79 | * @param retUrl 80 | * 返回地址 81 | * @return 82 | */ 83 | public static String encodeRetURL(String url, String retParam, String retUrl) { 84 | if (url == null) { 85 | return null; 86 | } 87 | StringBuffer retStr = new StringBuffer(url); 88 | retStr.append("?"); 89 | retStr.append(retParam); 90 | retStr.append("="); 91 | try { 92 | retStr.append(URLEncoder.encode(retUrl, SSOConfig.getEncoding())); 93 | } catch (UnsupportedEncodingException e) { 94 | e.printStackTrace(); 95 | } 96 | return retStr.toString(); 97 | } 98 | 99 | /** 100 | * GET 请求 101 | *

102 | * @param request 103 | * @return boolean 104 | */ 105 | public boolean isGet(HttpServletRequest request) { 106 | if ("GET".equalsIgnoreCase(request.getMethod())) { 107 | return true; 108 | } 109 | return false; 110 | } 111 | 112 | /** 113 | * POST 请求 114 | *

115 | * @param request 116 | * @return boolean 117 | */ 118 | public boolean isPost(HttpServletRequest request) { 119 | if ("POST".equalsIgnoreCase(request.getMethod())) { 120 | return true; 121 | } 122 | return false; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/common/util/PropertiesUtil.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso.common.util; 17 | 18 | import java.util.Properties; 19 | 20 | /** 21 | * Properties 工具类 22 | *

23 | * @author hubin 24 | * @Date 2014-5-12 25 | */ 26 | public class PropertiesUtil { 27 | 28 | private Properties properties; 29 | 30 | public PropertiesUtil(Properties properties) { 31 | this.properties = properties; 32 | } 33 | 34 | public String get(String key) { 35 | return properties.getProperty(key); 36 | } 37 | 38 | public String get(String key, String defaultVal) { 39 | String val = get(key); 40 | return val == null ? defaultVal : val; 41 | } 42 | 43 | public String findValue(String... keys) { 44 | for (String key : keys) { 45 | String value = get(key); 46 | if (value != null) { 47 | return value; 48 | } 49 | } 50 | return null; 51 | } 52 | 53 | public boolean getBoolean(String key, boolean defaultVal) { 54 | String val = get(key); 55 | return val == null ? defaultVal : Boolean.parseBoolean(val); 56 | } 57 | 58 | public long getLong(String key, long defaultVal) { 59 | String val = get(key); 60 | return val == null ? defaultVal : Long.parseLong(val); 61 | } 62 | 63 | public int getInt(String key, int defaultVal) { 64 | return (int) getLong(key, defaultVal); 65 | } 66 | 67 | public double getDouble(String key, double defaultVal) { 68 | String val = get(key); 69 | return val == null ? defaultVal : Double.parseDouble(val); 70 | } 71 | 72 | public > T getEnum(String key, Class type, T defaultValue) { 73 | String val = get(key); 74 | return val == null ? defaultValue : Enum.valueOf(type, val); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/common/util/RandomUtil.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso.common.util; 17 | 18 | import java.util.Random; 19 | import java.util.UUID; 20 | 21 | /** 22 | * 随机数工具类 23 | *

24 | * @author hubin 25 | * @Date 2014-5-9 26 | */ 27 | public class RandomUtil { 28 | 29 | /** 30 | * @Description 生产长度为length的随机字母数字混合字符串 31 | * @param length 32 | * 指定字符串长度 33 | * @return 34 | */ 35 | public static String getCharacterAndNumber(int length) { 36 | String val = ""; 37 | Random random = new Random(); 38 | for (int i = 0; i < length; i++) { 39 | // 输出字母还是数字 40 | String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num"; 41 | // 字符串 42 | if ("char".equalsIgnoreCase(charOrNum)) { 43 | // 取得大写字母还是小写字母 44 | int choice = random.nextInt(2) % 2 == 0 ? 65 : 97; 45 | val += (char) (choice + random.nextInt(26)); 46 | } 47 | // 数字 48 | else if ("num".equalsIgnoreCase(charOrNum)) { 49 | val += String.valueOf(random.nextInt(10)); 50 | } 51 | } 52 | return val; 53 | } 54 | 55 | /** 56 | * 获取去掉"-" UUID 57 | * @return 58 | */ 59 | public static String get32UUID() { 60 | return UUID.randomUUID().toString().replace("-", ""); 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/common/util/ReflectUtil.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso.common.util; 17 | 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | 21 | import com.github.tuzip.sso.SSOConfig; 22 | import com.github.tuzip.sso.SSOToken; 23 | import com.github.tuzip.sso.Token; 24 | import com.github.tuzip.sso.TokenCache; 25 | import com.github.tuzip.sso.TokenCacheMap; 26 | import com.github.tuzip.sso.common.encrypt.AES; 27 | import com.github.tuzip.sso.common.encrypt.Encrypt; 28 | import com.github.tuzip.sso.exception.KissoException; 29 | 30 | /** 31 | * 反射工具类 32 | *

33 | * @author hubin 34 | * @Date 2014-6-27 35 | */ 36 | public class ReflectUtil { 37 | private final static Logger logger = LoggerFactory.getLogger(ReflectUtil.class); 38 | 39 | /** 40 | * 反射获取自定义Encrypt 41 | * @return 42 | */ 43 | public static Encrypt getConfigEncrypt() { 44 | /** 45 | * 判断是否自定义 Encrypt 46 | * 默认 AES 47 | */ 48 | Encrypt encrypt = null; 49 | if("".equals(SSOConfig.getEncryptClass())){ 50 | encrypt = new AES(); 51 | } else { 52 | try { 53 | Class tc = Class.forName(SSOConfig.getEncryptClass()); 54 | try { 55 | if(tc.newInstance() instanceof Encrypt) { 56 | encrypt = (Encrypt) tc.newInstance(); 57 | } else { 58 | new KissoException(SSOConfig.getEncryptClass() + " not instanceof Encrypt."); 59 | } 60 | } catch (InstantiationException e) { 61 | e.printStackTrace(); 62 | } catch (IllegalAccessException e) { 63 | e.printStackTrace(); 64 | } 65 | } catch (ClassNotFoundException e) { 66 | e.printStackTrace(); 67 | logger.error("sso.encrypt.class. error..! " + SSOConfig.getEncryptClass()); 68 | } 69 | } 70 | return encrypt; 71 | } 72 | 73 | /** 74 | * 反射获取自定义Token 75 | * @return 76 | */ 77 | public static Token getConfigToken() { 78 | /** 79 | * 判断是否自定义 Token 80 | * 默认 SSOToken 81 | */ 82 | Token token = null; 83 | if("".equals(SSOConfig.getTokenClass())){ 84 | token = new SSOToken(); 85 | } else { 86 | try { 87 | Class tc = Class.forName(SSOConfig.getTokenClass()); 88 | try { 89 | if(tc.newInstance() instanceof Token) { 90 | token = (Token) tc.newInstance(); 91 | } else { 92 | new KissoException(SSOConfig.getTokenClass() + " not instanceof Token."); 93 | } 94 | } catch (InstantiationException e) { 95 | e.printStackTrace(); 96 | } catch (IllegalAccessException e) { 97 | e.printStackTrace(); 98 | } 99 | } catch (ClassNotFoundException e) { 100 | e.printStackTrace(); 101 | logger.error("sso.token.class. error..! " + SSOConfig.getTokenClass()); 102 | } 103 | } 104 | return token; 105 | } 106 | 107 | 108 | /** 109 | * 反射获取自定义TokenCache 110 | * @return 111 | */ 112 | public static TokenCache getConfigTokenCache() { 113 | /** 114 | * 判断是否自定义 TokenCache 115 | * 默认 TokenCacheMap 116 | */ 117 | TokenCache tokenCache = null; 118 | if("".equals(SSOConfig.getTokenCacheClass())){ 119 | tokenCache = new TokenCacheMap(); 120 | } else { 121 | try { 122 | Class tc = Class.forName(SSOConfig.getTokenCacheClass()); 123 | try { 124 | if(tc.newInstance() instanceof TokenCache) { 125 | tokenCache = (TokenCache) tc.newInstance(); 126 | } else { 127 | new KissoException(SSOConfig.getTokenCacheClass() + " not instanceof TokenCache."); 128 | } 129 | } catch (InstantiationException e) { 130 | e.printStackTrace(); 131 | } catch (IllegalAccessException e) { 132 | e.printStackTrace(); 133 | } 134 | } catch (ClassNotFoundException e) { 135 | e.printStackTrace(); 136 | logger.error("sso.tokencache.class. error..! " + SSOConfig.getTokenCacheClass()); 137 | } 138 | } 139 | return tokenCache; 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/exception/KissoException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso.exception; 17 | 18 | /** 19 | * SSO 异常 20 | *

21 | * @author hubin 22 | * @Date 2014-5-9 23 | */ 24 | public class KissoException extends RuntimeException { 25 | 26 | /** 27 | * 28 | */ 29 | private static final long serialVersionUID = 1L; 30 | 31 | public KissoException(String message) { 32 | super("Kisso exception.." + message); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/filter/SSOFilter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso.filter; 17 | 18 | import java.io.IOException; 19 | 20 | import javax.servlet.Filter; 21 | import javax.servlet.FilterChain; 22 | import javax.servlet.FilterConfig; 23 | import javax.servlet.ServletException; 24 | import javax.servlet.ServletRequest; 25 | import javax.servlet.ServletResponse; 26 | import javax.servlet.http.HttpServletRequest; 27 | import javax.servlet.http.HttpServletResponse; 28 | 29 | import org.slf4j.Logger; 30 | import org.slf4j.LoggerFactory; 31 | 32 | import com.github.tuzip.sso.Token; 33 | import com.github.tuzip.sso.client.SSOHelper; 34 | import com.github.tuzip.sso.common.util.HttpUtil; 35 | 36 | /** 37 | * SSO 过滤器验证登录状态 38 | *

39 | * @author hubin 40 | * @Date 2014-5-8 41 | */ 42 | public class SSOFilter implements Filter { 43 | private final static Logger logger = LoggerFactory.getLogger(SSOFilter.class); 44 | private static String OVERURL = null; 45 | 46 | @Override 47 | public void init(FilterConfig config) throws ServletException { 48 | /** 49 | * 从应用 web.xml 配置参数中 50 | * 获取不需要拦截URL 51 | */ 52 | OVERURL = config.getInitParameter("OVER.URL"); 53 | } 54 | 55 | @Override 56 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, 57 | ServletException { 58 | HttpServletRequest req = (HttpServletRequest) request; 59 | HttpServletResponse res = (HttpServletResponse) response; 60 | boolean isOver = HttpUtil.inContainURL(req, OVERURL); 61 | /** 非拦截URL、安全校验Cookie */ 62 | if (!isOver) { 63 | if (!(request instanceof HttpServletRequest) || !(response instanceof HttpServletResponse)) { 64 | logger.error("SSOFilter not http resource.."); 65 | throw new ServletException("此过滤器只保护HTTP资源"); 66 | } 67 | 68 | Token token = SSOHelper.getToken(req); 69 | if (token == null) { 70 | /** 71 | * 重新登录 72 | */ 73 | SSOHelper.loginAgain(req, res); 74 | } 75 | } 76 | chain.doFilter(request, response); 77 | } 78 | 79 | @Override 80 | public void destroy() { 81 | OVERURL = null; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/filter/WafFilter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso.filter; 17 | 18 | import java.io.IOException; 19 | 20 | import javax.servlet.Filter; 21 | import javax.servlet.FilterChain; 22 | import javax.servlet.FilterConfig; 23 | import javax.servlet.ServletException; 24 | import javax.servlet.ServletRequest; 25 | import javax.servlet.ServletResponse; 26 | import javax.servlet.http.HttpServletRequest; 27 | 28 | import org.slf4j.Logger; 29 | import org.slf4j.LoggerFactory; 30 | 31 | import com.github.tuzip.sso.common.util.HttpUtil; 32 | import com.github.tuzip.sso.waf.request.WafRequestWrapper; 33 | 34 | /** 35 | * Waf防火墙过滤器 36 | *

37 | * @author hubin 38 | * @Date 2014-5-8 39 | */ 40 | public class WafFilter implements Filter { 41 | private final static Logger logger = LoggerFactory.getLogger(WafFilter.class); 42 | private static String OVER_URL = null;//非过滤地址 43 | private static boolean FILTER_XSS = true;//开启XSS脚本过滤 44 | private static boolean FILTER_SQL = true;//开启SQL注入过滤 45 | 46 | @Override 47 | public void init(FilterConfig config) throws ServletException { 48 | //读取Web.xml配置地址 49 | OVER_URL = config.getInitParameter("over.url"); 50 | 51 | FILTER_XSS = getParamConfig(config.getInitParameter("filter_xss")); 52 | FILTER_SQL = getParamConfig(config.getInitParameter("filter_sql_injection")); 53 | logger.info(" WafFilter init . filter_xss: {} , filter_sql_injection: {} , FilterUrl:{}", new Object[] { 54 | FILTER_XSS, FILTER_SQL, OVER_URL }); 55 | } 56 | 57 | @Override 58 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, 59 | ServletException { 60 | logger.debug(" WafFilter doFilter ."); 61 | HttpServletRequest req = (HttpServletRequest) request; 62 | // HttpServletResponse res = (HttpServletResponse) response; 63 | 64 | boolean isOver = HttpUtil.inContainURL(req, OVER_URL); 65 | 66 | /** 非拦截URL、直接通过. */ 67 | if (!isOver) { 68 | logger.debug(" Yes doFilter ."); 69 | try { 70 | //Request请求XSS过滤 71 | chain.doFilter(new WafRequestWrapper(req, FILTER_XSS, FILTER_SQL), response); 72 | } catch (Exception e) { 73 | logger.error(" wafxx.jar WafFilter exception , requestURL: {}", req.getRequestURL()); 74 | e.printStackTrace(); 75 | } 76 | return; 77 | } 78 | 79 | chain.doFilter(request, response); 80 | } 81 | 82 | @Override 83 | public void destroy() { 84 | logger.debug(" WafFilter destroy ."); 85 | } 86 | 87 | /** 88 | * @Description 获取参数配置 89 | * @param value 90 | * 配置参数 91 | * @return 未配置返回 True 92 | */ 93 | private boolean getParamConfig(String value) { 94 | if (value == null || "".equals(value.trim())) { 95 | //未配置默认 True 96 | return true; 97 | } 98 | return new Boolean(value); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/filter/readme.txt: -------------------------------------------------------------------------------- 1 | 2 | ----------------------------------------------- 3 | web.xml配置 4 | ----------------------------------------------- 5 | 6 | 7 | WafFilter 8 | com.github.abci.kisso.filter.WafFilter 9 | 10 | over.url 11 | /test/a.html;/test/b.html 12 | 13 | 14 | config_tag 15 | sso 16 | 17 | 18 | filter_xss 19 | true 20 | 21 | 22 | filter_sql_injection 23 | true 24 | 25 | 26 | 27 | WafFilter 28 | /* 29 | 30 | ----------------------------------------------- 31 | 32 | 33 | log4j.properties配置 34 | ----------------------------------------------- 35 | log4j.appender.waf = org.apache.log4j.RollingFileAppender 36 | log4j.appender.waf.MaxFileSize=1MB 37 | log4j.appender.waf.MaxBackupIndex=7 38 | log4j.appender.waf.file = ${sso.root}/logs/waf.log 39 | log4j.appender.waf.layout = org.apache.log4j.PatternLayout 40 | log4j.appender.waf.layout.conversionPattern = %d [%t] %-5p %c - %m%n 41 | log4j.appender.waf.append = false 42 | 43 | ----------------------------------------------- 44 | 45 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/waf/WafHelper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso.waf; 17 | 18 | import com.github.tuzip.sso.waf.attack.SqlInjection; 19 | import com.github.tuzip.sso.waf.attack.XSS; 20 | 21 | /** 22 | * Web防火墙工具类 23 | *

24 | * @author hubin 25 | * @Date 2014-5-8 26 | */ 27 | public class WafHelper { 28 | 29 | /** 30 | * @Description 过滤XSS脚本内容 31 | * @param value 32 | * 待处理内容 33 | * @return 34 | */ 35 | public static String stripXSS(String value) { 36 | if (value == null) { 37 | return null; 38 | } 39 | 40 | return XSS.strip(value); 41 | } 42 | 43 | /** 44 | * @Description 过滤SQL注入内容 45 | * @param value 46 | * 待处理内容 47 | * @return 48 | */ 49 | public static String stripSqlInjection(String value) { 50 | if (value == null) { 51 | return null; 52 | } 53 | 54 | return SqlInjection.strip(value); 55 | } 56 | 57 | /** 58 | * @Description 过滤SQL/XSS注入内容 59 | * @param value 60 | * 待处理内容 61 | * @return 62 | */ 63 | public static String stripSqlXSS(String value) { 64 | if (value == null) { 65 | return null; 66 | } 67 | 68 | return XSS.strip(SqlInjection.strip(value)); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/waf/attack/SqlInjection.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso.waf.attack; 17 | 18 | /** 19 | * SQL注入攻击 20 | *

21 | * @author hubin 22 | * @Date 2014-5-8 23 | */ 24 | public class SqlInjection { 25 | 26 | /** 27 | * @Description SQL注入内容剥离 28 | * @param value 29 | * 待处理内容 30 | * @return 31 | */ 32 | public static String strip(String value) { 33 | 34 | //剥离SQL注入部分代码 35 | return value.replaceAll("('.+--)|(--)|(\\|)|(%7C)", ""); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /kisso/src/main/java/com/github/tuzip/sso/waf/attack/XSS.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2014, hubin (243194995@qq.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.tuzip.sso.waf.attack; 17 | 18 | import java.util.regex.Pattern; 19 | 20 | /** 21 | * XSS脚本攻击 22 | *

23 | * @author hubin 24 | * @Date 2014-5-8 25 | */ 26 | public class XSS { 27 | 28 | /** 29 | * @Description XSS脚本内容剥离 30 | * @param value 31 | * 待处理内容 32 | * @return 33 | */ 34 | public static String strip(String value) { 35 | if (value != null) { 36 | // NOTE: It's highly recommended to use the ESAPI library and uncomment the following line to 37 | // avoid encoded attacks. 38 | // value = ESAPI.encoder().canonicalize(value); 39 | 40 | // Avoid null characters 41 | value = value.replaceAll("", ""); 42 | 43 | // Avoid anything between script tags 44 | Pattern scriptPattern = Pattern.compile("", Pattern.CASE_INSENSITIVE); 45 | value = scriptPattern.matcher(value).replaceAll(""); 46 | 47 | // Avoid anything in a src='...' type of expression 48 | scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE 49 | | Pattern.MULTILINE | Pattern.DOTALL); 50 | value = scriptPattern.matcher(value).replaceAll(""); 51 | 52 | scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE 53 | | Pattern.MULTILINE | Pattern.DOTALL); 54 | value = scriptPattern.matcher(value).replaceAll(""); 55 | 56 | // Remove any lonesome tag 57 | scriptPattern = Pattern.compile("", Pattern.CASE_INSENSITIVE); 58 | value = scriptPattern.matcher(value).replaceAll(""); 59 | 60 | // Remove any lonesome