├── 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 | 
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 |
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
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 失败
135 | * @param request
136 | * @param response
137 | * @param TokenCache
138 | * @return boolean true 成功, false 失败
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
39 | * RSA公钥/私钥/签名工具包
40 | *
42 | * 罗纳德·李维斯特(Ron [R]ivest)、阿迪·萨莫尔(Adi [S]hamir)和伦纳德·阿德曼(Leonard [A]dleman)
43 | *
45 | * 字符串格式的密钥在未在特殊说明情况下都为BASE64编码格式
86 | * 生成密钥对(公钥和私钥)
87 | *
106 | * 用私钥对信息生成数字签名
107 | *
128 | * 校验数字签名
129 | *
152 | * 私钥解密
153 | *
190 | * 公钥解密
191 | *
228 | * 公钥加密
229 | *
267 | * 私钥加密
268 | *
305 | * 获取私钥
306 | *
319 | * 获取公钥
320 | *
35 | * BASE64编码解码工具包
36 | *
38 | * 依赖bcprov-jdk14-1.48.jar
39 | *
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 | *
66 | * 二进制数据编码为BASE64字符串
67 | *
104 | * 将文件编码为BASE64字符串
105 | *
107 | * 大文件慎用,可能会导致内存溢出
108 | *
121 | * BASE64字符串转回文件
122 | *
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 | *
188 | * 二进制数据写文件
189 | *
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
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 |
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
46 | * 由于非对称加密速度极其缓慢,一般文件不使用它来加密而是使用对称加密,
47 | * 非对称加密算法可以用来对对称加密的密钥加密,这样保证密钥的安全也就保证了数据的安全
48 | *