mirror of
https://github.com/ctripcorp/zeus.git
synced 2024-09-22 00:26:05 +08:00
Add internal token authorization mechanism
This commit is contained in:
parent
efeb6993a4
commit
1fdc46c677
|
@ -26,6 +26,8 @@ import java.util.Map;
|
|||
public class IPAuthenticationFilter implements Filter{
|
||||
private static final Logger logger = LoggerFactory.getLogger(IPAuthenticationFilter.class);
|
||||
DynamicStringProperty ipUserStr = DynamicPropertyFactory.getInstance().getStringProperty("ip.authentication", "127.0.0.1,172.16.144.61=releaseSys");
|
||||
private static final String SLB_SERVER_USER = "slbServer";
|
||||
public static final String SERVER_TOKEN_HEADER = "SlbServerToken";
|
||||
|
||||
private volatile Map<String, String> ipUserMap = new HashMap<>();
|
||||
|
||||
|
@ -52,18 +54,32 @@ public class IPAuthenticationFilter implements Filter{
|
|||
return;
|
||||
}
|
||||
|
||||
// check whether it is called from other slb servers.
|
||||
String slbServerToken = request.getHeader(SERVER_TOKEN_HEADER);
|
||||
if (slbServerToken != null){
|
||||
if (TokenManager.validateToken(slbServerToken)){
|
||||
setAssertion(request, SLB_SERVER_USER);
|
||||
filterChain.doFilter(request,response);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// if the request is from in ip white list, then authenticate it using the ip white list.
|
||||
String clientIP = getClientIP(request);
|
||||
String ipUser = getIpUser(clientIP);
|
||||
if (ipUser != null){
|
||||
logger.info("Authenticated by IP: " + clientIP + " Assigned userName:" + ipUser);
|
||||
assertion = new AssertionImpl(ipUser);
|
||||
request.setAttribute(AbstractCasFilter.CONST_CAS_ASSERTION, assertion);
|
||||
request.getSession().setAttribute(AbstractCasFilter.CONST_CAS_ASSERTION, assertion);
|
||||
setAssertion(request, ipUser);
|
||||
}
|
||||
filterChain.doFilter(request,response);
|
||||
}
|
||||
|
||||
private void setAssertion(HttpServletRequest request, String userName) {
|
||||
Assertion assertion = new AssertionImpl(userName);
|
||||
request.setAttribute(AbstractCasFilter.CONST_CAS_ASSERTION, assertion);
|
||||
request.getSession().setAttribute(AbstractCasFilter.CONST_CAS_ASSERTION, assertion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
// nothing to do
|
||||
|
|
109
src/main/java/com/ctrip/zeus/auth/impl/TokenManager.java
Normal file
109
src/main/java/com/ctrip/zeus/auth/impl/TokenManager.java
Normal file
|
@ -0,0 +1,109 @@
|
|||
package com.ctrip.zeus.auth.impl;
|
||||
|
||||
import com.ctrip.zeus.dal.core.AuthPrivateKeyDao;
|
||||
import com.ctrip.zeus.dal.core.AuthPrivateKeyDo;
|
||||
import com.ctrip.zeus.dal.core.AuthPrivateKeyEntity;
|
||||
import com.ctrip.zeus.support.DaoFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sun.misc.BASE64Decoder;
|
||||
import sun.misc.BASE64Encoder;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.DESKeySpec;
|
||||
import java.security.Key;
|
||||
|
||||
/**
|
||||
* User: mag
|
||||
* Date: 5/14/2015
|
||||
* Time: 5:27 PM
|
||||
*/
|
||||
public class TokenManager {
|
||||
private static final Logger logger = LoggerFactory.getLogger(TokenManager.class);
|
||||
public static final String ALGORITHM = "DES";
|
||||
private static String privateKey = "slbPrivateKey";
|
||||
|
||||
static {
|
||||
try {
|
||||
AuthPrivateKeyDao dao = new DaoFactory().getDao(AuthPrivateKeyDao.class);
|
||||
AuthPrivateKeyDo privateKeyDo = dao.findFirst(AuthPrivateKeyEntity.READSET_FULL);
|
||||
privateKey = privateKeyDo.getPrivateKey();
|
||||
}catch (Exception e){
|
||||
logger.error("error fetch private key from db.",e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String generateToken() {
|
||||
long currTime = System.currentTimeMillis();
|
||||
byte[] timeBytes = toBytes(currTime);
|
||||
try {
|
||||
Key k = toKey(privateKey.getBytes("UTF-8"));
|
||||
Cipher cipher = Cipher.getInstance(ALGORITHM);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, k);
|
||||
return encryptBASE64(cipher.doFinal(timeBytes));
|
||||
}catch (Exception e){
|
||||
logger.error("error when generate token",e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean validateToken(String token) {
|
||||
try {
|
||||
Key key = toKey(privateKey.getBytes("UTF-8"));
|
||||
Cipher cipher = Cipher.getInstance(ALGORITHM);
|
||||
cipher.init(Cipher.DECRYPT_MODE, key);
|
||||
long currTime = System.currentTimeMillis();
|
||||
long decryptedTime = toLong(cipher.doFinal(decryptBASE64(token)));
|
||||
if ((currTime - decryptedTime) < 60000){
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("validate token fail!",e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static byte[] decryptBASE64(String key) throws Exception {
|
||||
return (new BASE64Decoder()).decodeBuffer(key);
|
||||
}
|
||||
|
||||
|
||||
private static String encryptBASE64(byte[] key) throws Exception {
|
||||
return (new BASE64Encoder()).encodeBuffer(key);
|
||||
}
|
||||
|
||||
private static Key toKey(byte[] key) throws Exception {
|
||||
DESKeySpec dks = new DESKeySpec(key);
|
||||
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
|
||||
SecretKey secretKey = keyFactory.generateSecret(dks);
|
||||
return secretKey;
|
||||
}
|
||||
|
||||
private static byte[] toBytes(long value){
|
||||
byte[] result = new byte[8];
|
||||
long tmp = value;
|
||||
for (int i = 7; i >= 0; i--) {
|
||||
result[i] = (byte) (tmp & (0xFFL));
|
||||
tmp = tmp >> 8;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static long toLong(byte[] value) {
|
||||
long rt = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
int add = value[i] & (0xFF);
|
||||
rt = rt << 8;
|
||||
rt += add;
|
||||
}
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception{
|
||||
String token = TokenManager.generateToken();
|
||||
System.out.println("token:" + token);
|
||||
System.out.println("validate token:" + TokenManager.validateToken(token));
|
||||
}
|
||||
}
|
|
@ -1,11 +1,16 @@
|
|||
package com.ctrip.zeus.client;
|
||||
|
||||
import com.ctrip.zeus.auth.impl.IPAuthenticationFilter;
|
||||
import com.ctrip.zeus.auth.impl.TokenManager;
|
||||
import org.glassfish.jersey.client.ClientConfig;
|
||||
import org.glassfish.jersey.uri.UriComponent;
|
||||
|
||||
import javax.ws.rs.client.Client;
|
||||
import javax.ws.rs.client.ClientBuilder;
|
||||
import javax.ws.rs.client.Invocation;
|
||||
import javax.ws.rs.client.WebTarget;
|
||||
import javax.ws.rs.core.MultivaluedHashMap;
|
||||
import javax.ws.rs.core.MultivaluedMap;
|
||||
|
||||
/**
|
||||
* @author:xingchaowang
|
||||
|
@ -28,4 +33,10 @@ public abstract class AbstractRestClient {
|
|||
protected WebTarget getTarget(){
|
||||
return webTarget;
|
||||
}
|
||||
|
||||
protected MultivaluedMap<String, Object> getDefaultHeaders(){
|
||||
MultivaluedMap<String, Object> map = new MultivaluedHashMap<>();
|
||||
map.putSingle(IPAuthenticationFilter.SERVER_TOKEN_HEADER, TokenManager.generateToken());
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,12 +20,12 @@ public class AppClient extends AbstractRestClient {
|
|||
}
|
||||
|
||||
public List<App> getAll() {
|
||||
String res = getTarget().path("/api/app").request().get(String.class);
|
||||
String res = getTarget().path("/api/app").request().headers(getDefaultHeaders()).get(String.class);
|
||||
return null;
|
||||
}
|
||||
|
||||
public Response add(App app) {
|
||||
return getTarget().path("/api/app/add").request()
|
||||
return getTarget().path("/api/app/add").request().headers(getDefaultHeaders())
|
||||
.post(Entity.entity(
|
||||
String.format(App.JSON, app),
|
||||
MediaType.APPLICATION_JSON
|
||||
|
@ -34,7 +34,7 @@ public class AppClient extends AbstractRestClient {
|
|||
}
|
||||
|
||||
public App get(String appName) {
|
||||
String res = getTarget().path("/api/app/get/" + appName).request(MediaType.APPLICATION_JSON).get(String.class);
|
||||
String res = getTarget().path("/api/app/get/" + appName).request(MediaType.APPLICATION_JSON).headers(getDefaultHeaders()).get(String.class);
|
||||
try {
|
||||
return DefaultJsonParser.parse(App.class, res);
|
||||
} catch (IOException e) {
|
||||
|
|
|
@ -42,24 +42,24 @@ public class NginxClient extends AbstractRestClient {
|
|||
|
||||
|
||||
public NginxResponse load() throws IOException{
|
||||
String responseStr = getTarget().path("/api/nginx/load").request().get(String.class);
|
||||
String responseStr = getTarget().path("/api/nginx/load").request().headers(getDefaultHeaders()).get(String.class);
|
||||
return DefaultJsonParser.parse(NginxResponse.class, responseStr);
|
||||
}
|
||||
|
||||
public NginxResponse write()throws IOException{
|
||||
String responseStr = getTarget().path("/api/nginx/write").request().get(String.class);
|
||||
String responseStr = getTarget().path("/api/nginx/write").request().headers(getDefaultHeaders()).get(String.class);
|
||||
return DefaultJsonParser.parse(NginxResponse.class, responseStr);
|
||||
}
|
||||
|
||||
public NginxResponse dyups(String upsName ,String upsCommands)throws IOException{
|
||||
String responseStr = getTarget().path("/api/nginx/dyups/"+upsName).request().post(Entity.entity(upsCommands,
|
||||
String responseStr = getTarget().path("/api/nginx/dyups/" + upsName).request().headers(getDefaultHeaders()).post(Entity.entity(upsCommands,
|
||||
MediaType.APPLICATION_JSON
|
||||
),String.class);
|
||||
return DefaultJsonParser.parse(NginxResponse.class,responseStr);
|
||||
}
|
||||
|
||||
public TrafficStatus getTrafficStatus() throws Exception {
|
||||
Response response = getTarget().path("").path("/api/nginx/trafficStatus").request().get();
|
||||
Response response = getTarget().path("").path("/api/nginx/trafficStatus").request().headers(getDefaultHeaders()).get();
|
||||
InputStream is = (InputStream)response.getEntity();
|
||||
try {
|
||||
return DefaultJsonParser.parse(TrafficStatus.class, IOUtils.inputStreamStringify(is));
|
||||
|
|
|
@ -20,12 +20,12 @@ public class SlbClient extends AbstractRestClient {
|
|||
}
|
||||
|
||||
public List<Slb> getAll() {
|
||||
String res = getTarget().path("/api/slb").request().get(String.class);
|
||||
String res = getTarget().path("/api/slb").request().headers(getDefaultHeaders()).get(String.class);
|
||||
return null;
|
||||
}
|
||||
|
||||
public Response add(Slb slb) {
|
||||
return getTarget().path("/api/slb/add").request()
|
||||
return getTarget().path("/api/slb/add").request().headers(getDefaultHeaders())
|
||||
.post(Entity.entity(
|
||||
String.format(Slb.JSON, slb),
|
||||
MediaType.APPLICATION_JSON
|
||||
|
@ -33,7 +33,7 @@ public class SlbClient extends AbstractRestClient {
|
|||
}
|
||||
|
||||
public Response update(Slb slb) {
|
||||
return getTarget().path("/api/slb/update").request()
|
||||
return getTarget().path("/api/slb/update").request().headers(getDefaultHeaders())
|
||||
.post(Entity.entity(
|
||||
String.format(Slb.JSON, slb),
|
||||
MediaType.APPLICATION_JSON
|
||||
|
@ -41,7 +41,7 @@ public class SlbClient extends AbstractRestClient {
|
|||
}
|
||||
|
||||
public Slb get(String slbName) {
|
||||
String res = getTarget().path("/api/slb/get/" + slbName).request(MediaType.APPLICATION_JSON).get(String.class);
|
||||
String res = getTarget().path("/api/slb/get/" + slbName).request(MediaType.APPLICATION_JSON).headers(getDefaultHeaders()).get(String.class);
|
||||
try {
|
||||
return DefaultJsonParser.parse(Slb.class, res);
|
||||
} catch (IOException e) {
|
||||
|
|
|
@ -177,5 +177,17 @@
|
|||
</query>
|
||||
</query-defs>
|
||||
</entity>
|
||||
<entity name="auth-private-key" table="auth_private_key" alias="apk" do-class="AuthPrivateKeyDo">
|
||||
<query-defs>
|
||||
<query name="find-first" type="SELECT">
|
||||
<statement>
|
||||
<![CDATA[
|
||||
SELECT <FIELDS/>
|
||||
FROM <TABLE/>
|
||||
]]>
|
||||
</statement>
|
||||
</query>
|
||||
</query-defs>
|
||||
</entity>
|
||||
</entities>
|
||||
|
||||
|
|
|
@ -287,6 +287,42 @@
|
|||
</query>
|
||||
</query-defs>
|
||||
</entity>
|
||||
<entity name="auth-private-key" table="auth_private_key" alias="apk">
|
||||
<member name="private-key" field="private_key" value-type="String" length="50" nullable="false" key="true" />
|
||||
<member name="data-change-last-time" field="DataChange_LastTime" value-type="Date" nullable="false" />
|
||||
<var name="key-private-key" value-type="String" key-member="private-key" />
|
||||
<primary-key name="PRIMARY" members="private_key" />
|
||||
<index name="time idx" members="DataChange_LastTime ASC" />
|
||||
<readsets>
|
||||
<readset name="FULL" all="true" />
|
||||
</readsets>
|
||||
<updatesets>
|
||||
<updateset name="FULL" all="true" />
|
||||
</updatesets>
|
||||
<query-defs>
|
||||
<query name="find-by-PK" type="SELECT">
|
||||
<param name="key-private-key" />
|
||||
<statement><![CDATA[SELECT <FIELDS/>
|
||||
FROM <TABLE/>
|
||||
WHERE <FIELD name='private-key'/> = ${key-private-key}]]></statement>
|
||||
</query>
|
||||
<query name="insert" type="INSERT">
|
||||
<statement><![CDATA[INSERT INTO <TABLE/>(<FIELDS/>)
|
||||
VALUES(<VALUES/>)]]></statement>
|
||||
</query>
|
||||
<query name="update-by-PK" type="UPDATE">
|
||||
<param name="key-private-key" />
|
||||
<statement><![CDATA[UPDATE <TABLE/>
|
||||
SET <FIELDS/>
|
||||
WHERE <FIELD name='private-key'/> = ${key-private-key}]]></statement>
|
||||
</query>
|
||||
<query name="delete-by-PK" type="DELETE">
|
||||
<param name="key-private-key" />
|
||||
<statement><![CDATA[DELETE FROM <TABLE/>
|
||||
WHERE <FIELD name='private-key'/> = ${key-private-key}]]></statement>
|
||||
</query>
|
||||
</query-defs>
|
||||
</entity>
|
||||
<entity name="auth-resource" table="auth_resource" alias="ar">
|
||||
<member name="id" field="id" value-type="int" length="10" nullable="false" key="true" auto-increment="true" />
|
||||
<member name="resource-name" field="resource_name" value-type="String" length="100" nullable="false" />
|
||||
|
@ -296,6 +332,7 @@
|
|||
<member name="data-change-last-time" field="DataChange_LastTime" value-type="Date" nullable="false" />
|
||||
<var name="key-id" value-type="int" key-member="id" />
|
||||
<primary-key name="PRIMARY" members="id" />
|
||||
<index name="time_idx" members="DataChange_LastTime ASC" />
|
||||
<readsets>
|
||||
<readset name="FULL" all="true" />
|
||||
</readsets>
|
||||
|
@ -336,6 +373,7 @@
|
|||
<primary-key name="PRIMARY" members="id" />
|
||||
<index name="role_idx" members="role_name ASC" />
|
||||
<index name="res_idx" members="resource_name ASC" />
|
||||
<index name="time_idx" members="DataChange_LastTime ASC" />
|
||||
<readsets>
|
||||
<readset name="FULL" all="true" />
|
||||
</readsets>
|
||||
|
@ -375,6 +413,7 @@
|
|||
<var name="key-id" value-type="int" key-member="id" />
|
||||
<primary-key name="PRIMARY" members="id" />
|
||||
<index name="role_idx" unique="true" members="role_name ASC" />
|
||||
<index name="time_idx" members="DataChange_LastTime ASC" />
|
||||
<readsets>
|
||||
<readset name="FULL" all="true" />
|
||||
</readsets>
|
||||
|
@ -407,13 +446,14 @@
|
|||
</entity>
|
||||
<entity name="auth-user" table="auth_user" alias="au">
|
||||
<member name="id" field="id" value-type="int" length="10" nullable="false" key="true" auto-increment="true" />
|
||||
<member name="user-name" field="user_name" value-type="String" length="50" nullable="false" />
|
||||
<member name="user-name" field="user_name" value-type="String" length="50" />
|
||||
<member name="description" field="description" value-type="String" length="100" />
|
||||
<member name="created-time" field="created_time" value-type="Date" />
|
||||
<member name="data-change-last-time" field="DataChange_LastTime" value-type="Date" nullable="false" />
|
||||
<var name="key-id" value-type="int" key-member="id" />
|
||||
<primary-key name="PRIMARY" members="id" />
|
||||
<index name="usr_name_idx" unique="true" members="user_name ASC" />
|
||||
<index name="time_idx" members="DataChange_LastTime ASC" />
|
||||
<readsets>
|
||||
<readset name="FULL" all="true" />
|
||||
</readsets>
|
||||
|
@ -446,15 +486,15 @@
|
|||
</entity>
|
||||
<entity name="auth-user-role" table="auth_user_role" alias="aur">
|
||||
<member name="id" field="id" value-type="int" length="10" nullable="false" key="true" auto-increment="true" />
|
||||
<member name="user-name" field="user_name" value-type="String" length="50" nullable="false" />
|
||||
<member name="role-name" field="role_name" value-type="String" length="50" nullable="false" />
|
||||
<member name="group" field="group" value-type="String" length="50" nullable="false" />
|
||||
<member name="user-name" field="user_name" value-type="String" length="50" />
|
||||
<member name="role-name" field="role_name" value-type="String" length="50" />
|
||||
<member name="group" field="group" value-type="String" length="50" />
|
||||
<member name="created-time" field="created_time" value-type="Date" />
|
||||
<member name="data-change-last-time" field="DataChange_LastTime" value-type="Date" nullable="false" />
|
||||
<var name="key-id" value-type="int" key-member="id" />
|
||||
<primary-key name="PRIMARY" members="id" />
|
||||
<index name="usr_role_idx" unique="true" members="user_name ASC" />
|
||||
<index name="usr_idx" members="user_name ASC" />
|
||||
<index name="time_idx" members="DataChange_LastTime ASC" />
|
||||
<readsets>
|
||||
<readset name="FULL" all="true" />
|
||||
</readsets>
|
||||
|
@ -566,7 +606,7 @@
|
|||
</query-defs>
|
||||
</entity>
|
||||
<entity name="conf-app-slb-active" table="conf_app_slb_active" alias="casa">
|
||||
<member name="id" field="id" value-type="long" length="19" nullable="false" key="true" />
|
||||
<member name="id" field="id" value-type="long" length="19" nullable="false" key="true" auto-increment="true" />
|
||||
<member name="app-name" field="app_name" value-type="String" length="200" nullable="false" />
|
||||
<member name="slb-name" field="slb_name" value-type="String" length="200" nullable="false" />
|
||||
<member name="slb-virtual-server-name" field="slb_virtual_server_name" value-type="String" length="200" nullable="false" />
|
||||
|
@ -646,9 +686,11 @@
|
|||
</entity>
|
||||
<entity name="dist-lock" table="dist_lock" alias="dl">
|
||||
<member name="lock-key" field="lock_key" value-type="String" length="255" nullable="false" key="true" />
|
||||
<member name="created-time" field="created_time" value-type="long" length="19" nullable="false" />
|
||||
<member name="created-time" field="created_time" value-type="long" length="19" />
|
||||
<member name="data-change-last-time" field="DataChange_LastTime" value-type="Date" nullable="false" />
|
||||
<var name="key-lock-key" value-type="String" key-member="lock-key" />
|
||||
<primary-key name="PRIMARY" members="lock_key" />
|
||||
<index name="dcl_key" members="DataChange_LastTime ASC" />
|
||||
<readsets>
|
||||
<readset name="FULL" all="true" />
|
||||
</readsets>
|
||||
|
|
|
@ -71,6 +71,15 @@
|
|||
<data-source-name>zeus</data-source-name>
|
||||
</configuration>
|
||||
</component>
|
||||
<component>
|
||||
<role>org.unidal.dal.jdbc.mapping.TableProvider</role>
|
||||
<role-hint>auth-private-key</role-hint>
|
||||
<implementation>org.unidal.dal.jdbc.mapping.SimpleTableProvider</implementation>
|
||||
<configuration>
|
||||
<physical-table-name>auth_private_key</physical-table-name>
|
||||
<data-source-name>zeus</data-source-name>
|
||||
</configuration>
|
||||
</component>
|
||||
<component>
|
||||
<role>org.unidal.dal.jdbc.mapping.TableProvider</role>
|
||||
<role-hint>auth-resource</role-hint>
|
||||
|
@ -332,6 +341,15 @@
|
|||
</requirement>
|
||||
</requirements>
|
||||
</component>
|
||||
<component>
|
||||
<role>com.ctrip.zeus.dal.core.AuthPrivateKeyDao</role>
|
||||
<implementation>com.ctrip.zeus.dal.core.AuthPrivateKeyDao</implementation>
|
||||
<requirements>
|
||||
<requirement>
|
||||
<role>org.unidal.dal.jdbc.QueryEngine</role>
|
||||
</requirement>
|
||||
</requirements>
|
||||
</component>
|
||||
<component>
|
||||
<role>com.ctrip.zeus.dal.core.AuthResourceDao</role>
|
||||
<implementation>com.ctrip.zeus.dal.core.AuthResourceDao</implementation>
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
<table name="auth_resource_role"/>
|
||||
<table name="auth_user_role"/>
|
||||
<table name="auth_user"/>
|
||||
<table name="auth_private_key"/>
|
||||
</group>
|
||||
</jdbc>
|
||||
</wizard>
|
||||
|
|
Loading…
Reference in a new issue