【发布时间】:2018-03-16 19:23:56
【问题描述】:
我是 JAX-RS 和 REST-API 的新手。
我正在使用 REST 服务从 Oracle 获取行。我已将连接详细信息放在META-INF/context.xml 的<Resource> 标记中,我已在其中加密了password 变量。
我有一个自定义 Encrypter 类,我在其中使用我在 Encrypter 类中硬编码的密钥对密码进行加密/解密。
我的要求是我希望将此密钥设置在某个变量(可能是上下文变量)中,以便当用户点击像"http://server:8080/myapp/rest/replay/getdata?skey=3456FGR55566DHGGH556gf" 这样的 GET 方法 URL 时,我可以从 URL 中获取 skey 参数并将其与上下文进行比较-我从我的 Encryptor 类中设置的变量。如果两者都匹配,则显示 JSON 数据,否则将重定向到 JSP。
除了我无法在我的 Encryptor 类中设置这个 secretKey 变量之外,一切都运行良好。
以下是代码流程:
public class AuthenticatedEncryptor {
private static final String ALGORITHM_AES256 = "AES/GCM/NoPadding";
private final SecretKeySpec secretKeySpec;
private final Cipher cipher;
// All other variables...
//@Context ServletContext context
AuthenticatedEncryptor() throws AuthenticatedEncryptionException
{
String secretKey = "9B7D2C34A366BF890C730641E6CECF6F";
//Here I want to set the above variable in Context like:
//context.setAttriute("skey",secretKey);
//Code for Constructor
}
/*
* Encrypts plaint text. Returns Encrypted String.
*/
String encrypt(String plaintext) throws AuthenticatedEncryptionException
{
return encrypt(plaintext.getBytes(StandardCharsets.UTF_8));
}
String encrypt(byte[] plaintext) throws AuthenticatedEncryptionException
{
try
{
byte[] iv = getRandom(IV_LEN);
Cipher msgcipher = getCipher(Cipher.ENCRYPT_MODE, iv);
byte[] encryptedTextBytes = msgcipher.doFinal(plaintext);
byte[] payload = concat(iv, encryptedTextBytes);
return Base64.getEncoder().encodeToString(payload);
}
catch (BadPaddingException | InvalidKeyException | IllegalBlockSizeException | InvalidAlgorithmParameterException e){
throw new AuthenticatedEncryptionException(e);
}
}
/*
* Decrypts plaint text. Returns decrypted String.
*/
String decrypt(String ciphertext) throws AuthenticatedEncryptionException
{
return decrypt(Base64.getDecoder().decode(ciphertext));
}
String decrypt(byte[] cipherBytes) throws AuthenticatedEncryptionException
{
byte[] iv = Arrays.copyOf(cipherBytes, IV_LEN);
byte[] cipherText = Arrays.copyOfRange(cipherBytes, IV_LEN, cipherBytes.length);
try {
Cipher cipher = getCipher(Cipher.DECRYPT_MODE, iv);
byte[] decrypt = cipher.doFinal(cipherText);
return new String(decrypt, StandardCharsets.UTF_8);
} catch (BadPaddingException | InvalidKeyException | IllegalBlockSizeException | InvalidAlgorithmParameterException e) {
throw new AuthenticatedEncryptionException(e);
}
}
//All other utility methods present here....
}
上面的类用在我自定义的DataSourceFactory类中:
public class EncryptedDataSourceFactory extends DataSourceFactory {
private AuthenticatedEncryptor encryptor = null;
public EncryptedDataSourceFactory() {
try
{
encryptor = new AuthenticatedEncryptor();
}
catch (Exception e) {
System.out.println("Incorrect Secret-Key specified for Decryption in EncryptedDataSourceFactory.class");
throw new RuntimeException(e);
}
}
@Override
public DataSource createDataSource(Properties properties, Context context, boolean XA) throws Exception
{
// Here we decrypt our password.
PoolConfiguration poolProperties = EncryptedDataSourceFactory.parsePoolProperties(properties);
poolProperties.setPassword(encryptor.decrypt(poolProperties.getPassword()));
// The rest of the code is copied from Tomcat's DataSourceFactory.
if(poolProperties.getDataSourceJNDI() != null && poolProperties.getDataSource() == null) {
performJNDILookup(context, poolProperties);
}
org.apache.tomcat.jdbc.pool.DataSource dataSource = XA ? new XADataSource(poolProperties)
: new org.apache.tomcat.jdbc.pool.DataSource(poolProperties);
dataSource.createPool();
return dataSource;
}
}
我公开为 GET 的代码:
@Path("/replay")
public class GetData {
@Context
private ServletContext context;
Logger logger = Logger.getLogger(GetData.class.getName());
@GET
@Path("/getdata")
@Produces(MediaType.APPLICATION_JSON)
public String getReplayData(@Context HttpHeaders httpHeaders, @Context HttpServletRequest req, @Context HttpServletResponse res)
{
/* Loading all HeaderParams */
List<String> headers = new ArrayList<String>();
for(String header : httpHeaders.getRequestHeaders().keySet()){
headers.add(header);
}
//...
//....
/*Printing all HeaderParams */
headerValue.forEach((k,v)->logger.info("HEADER: " + k + "-->" + v));
/* Redirecting Code */
//I need to access this SKEY attribute I want to set in my Encryptor
String secretKey = (String)context.getAttribute("skey");
System.out.println("SECRET KEY: "+secretKey);
boolean redirect = false;
String redirectVal = headerValue.get("x-test-redirect");
if(redirectVal!=null && redirectVal.equalsIgnoreCase("Y")){
redirect = true;
}
if(redirect)
{
try
{
logger.info("Authentication failed for Secret Key. Redirecting to authFailed.jsp...");
req.getRequestDispatcher("/authFailed.jsp").forward(req, res);
} catch(Exception e){
System.out.println("Error in redirecting");
logger.severe("Error in redirecting");
logger.log(Level.SEVERE, e.getMessage(), e);
}
}
OracleConn con1 = new OracleConn(env, logPath);
ResultSet result = con1.exec("select * from mytable");
System.out.println("Result: "+result.toString());
logger.info("Result: "+result.toString());
//parse data to JSON
JSONArray json = parseJSON(result);
System.out.println("Result parsed to JSON");
logger.info("Result parsed to JSON");
try{
con1.close();
return json.toString();
} catch(Exception e){
e.printStackTrace();
logger.log(Level.SEVERE, e.getMessage(), e);
return "Corrupted JSON";
}
}
}
如何在我的AuthenticatedEncryptor 类中设置一个变量并在我的网络服务类GetData 中获取它的值?
【问题讨论】:
-
CDI 可用吗?
标签: java rest web-services jax-rs