Authentication manager added.

This commit is contained in:
Zhen Tang 2013-06-24 12:19:17 +08:00
parent 8e29051975
commit 4ffdbca835
11 changed files with 574 additions and 15 deletions

View File

@ -0,0 +1,40 @@
package org.bench4q.master.api;
import javax.servlet.http.HttpServletRequest;
import org.bench4q.master.auth.AuthenticationManager;
import org.bench4q.master.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
public abstract class BaseController {
private HttpServletRequest request;
private AuthenticationManager authenticationManager;
protected HttpServletRequest getRequest() {
return request;
}
@Autowired
protected void setRequest(HttpServletRequest request) {
this.request = request;
}
protected AuthenticationManager getAuthenticationManager() {
return authenticationManager;
}
@Autowired
protected void setAuthenticationManager(
AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
protected User getPrincipal() {
return this.getAuthenticationManager().getPrincipal(this.getRequest());
}
protected boolean checkScope(String scope) {
return this.getAuthenticationManager().checkScope(this.getRequest(),
scope);
}
}

View File

@ -1,16 +1,24 @@
package org.bench4q.master.api;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/")
public class HomeController {
@RequestMapping(value = { "/" }, method = RequestMethod.GET)
@ResponseBody
public String index() {
return "It works!";
}
package org.bench4q.master.api;
import org.bench4q.master.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/")
public class HomeController extends BaseController {
@RequestMapping(value = { "/" }, method = RequestMethod.GET)
@ResponseBody
public String index() {
User principal = this.getPrincipal();
String userName;
if (principal == null) {
userName = "Anonymous User";
} else {
userName = principal.getUserName();
}
return "Hello [" + userName + "]";
}
}

View File

@ -0,0 +1,75 @@
package org.bench4q.master.api;
import org.bench4q.master.api.model.AuthorizeResponseModel;
import org.bench4q.master.api.model.RegisterResponseModel;
import org.bench4q.master.auth.AccessToken;
import org.bench4q.master.auth.AuthenticationManager;
import org.bench4q.master.entity.User;
import org.bench4q.master.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/user")
public class UserController {
private UserService userService;
private AuthenticationManager authenticationManager;
private UserService getUserService() {
return userService;
}
@Autowired
private void setUserService(UserService userService) {
this.userService = userService;
}
public AuthenticationManager getAuthenticationManager() {
return authenticationManager;
}
@Autowired
public void setAuthenticationManager(
AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@RequestMapping(value = "/register", method = RequestMethod.GET)
@ResponseBody
public RegisterResponseModel register(@RequestParam String userName,
@RequestParam String password) {
boolean success = this.getUserService().register(userName, password);
RegisterResponseModel registerUserResponseModel = new RegisterResponseModel();
registerUserResponseModel.setSuccess(success);
return registerUserResponseModel;
}
@RequestMapping(value = "/authorize", method = RequestMethod.GET)
@ResponseBody
public AuthorizeResponseModel authorize(@RequestParam String userName,
@RequestParam String password) {
boolean authorized = this.getUserService().validateUser(userName,
password);
if (!authorized) {
AuthorizeResponseModel responseModel = new AuthorizeResponseModel();
responseModel.setAccessToken(null);
responseModel.setExpiresIn(-1);
responseModel.setSuccess(false);
return responseModel;
}
User user = this.getUserService().getUserByName(userName);
AccessToken accessToken = this.getAuthenticationManager()
.generateAccessToken(user);
String credential = this.getAuthenticationManager().generateCredential(
user);
AuthorizeResponseModel responseModel = new AuthorizeResponseModel();
responseModel.setAccessToken(credential);
responseModel.setExpiresIn(accessToken.getExpiresIn());
responseModel.setSuccess(true);
return responseModel;
}
}

View File

@ -0,0 +1,40 @@
package org.bench4q.master.api.model;
import javax.xml.bind.annotation.XmlRootElement;
import com.sun.xml.internal.txw2.annotation.XmlElement;
@XmlRootElement(name = "authorizeResponse")
public class AuthorizeResponseModel {
private boolean success;
private String accessToken;
private int expiresIn;
@XmlElement
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
@XmlElement
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
@XmlElement
public int getExpiresIn() {
return expiresIn;
}
public void setExpiresIn(int expiresIn) {
this.expiresIn = expiresIn;
}
}

View File

@ -0,0 +1,20 @@
package org.bench4q.master.api.model;
import javax.xml.bind.annotation.XmlRootElement;
import com.sun.xml.internal.txw2.annotation.XmlElement;
@XmlRootElement(name = "registerResponse")
public class RegisterResponseModel {
private boolean success;
@XmlElement
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
}

View File

@ -0,0 +1,55 @@
package org.bench4q.master.auth;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
public class AccessToken implements Serializable {
private static final long serialVersionUID = 4134631390384650898L;
private String userName;
private String password;
private Date generateTime;
private int expiresIn;
private List<String> scope;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getGenerateTime() {
return generateTime;
}
public void setGenerateTime(Date generateTime) {
this.generateTime = generateTime;
}
public int getExpiresIn() {
return expiresIn;
}
public void setExpiresIn(int expiresIn) {
this.expiresIn = expiresIn;
}
public List<String> getScope() {
return scope;
}
public void setScope(List<String> scope) {
this.scope = scope;
}
}

View File

@ -0,0 +1,138 @@
package org.bench4q.master.auth;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import org.bench4q.master.entity.User;
import org.bench4q.master.helper.StringHelper;
import org.bench4q.master.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class AuthenticationManager {
private final int defaultExpiresTime = 3600;
private CryptoManager cryptoManager;
private UserService userService;
private StringHelper stringHelper;
private CryptoManager getCryptoManager() {
return cryptoManager;
}
@Autowired
private void setCryptoManager(CryptoManager cryptoManager) {
this.cryptoManager = cryptoManager;
}
private UserService getUserService() {
return userService;
}
@Autowired
private void setUserService(UserService userService) {
this.userService = userService;
}
private StringHelper getStringHelper() {
return stringHelper;
}
@Autowired
private void setStringHelper(StringHelper stringHelper) {
this.stringHelper = stringHelper;
}
public User getPrincipal(HttpServletRequest request) {
AccessToken accessToken = this.getAccessToken(request);
if (accessToken == null) {
return null;
}
return this.extractUser(accessToken);
}
public boolean checkScope(HttpServletRequest request, String scope) {
AccessToken accessToken = this.getAccessToken(request);
if (accessToken == null) {
return false;
}
return accessToken.getScope().contains(scope);
}
public String generateCredential(User user) {
AccessToken accessToken = this.generateAccessToken(user);
return this.generateCredentialFromAccessToken(accessToken);
}
private AccessToken getAccessToken(HttpServletRequest request) {
if (request.getHeader("Authorization") == null) {
return null;
}
if (!request.getHeader("Authorization").startsWith("Bearer ")) {
return null;
}
String hex = request.getHeader("Authorization").substring(
"Bearer ".length());
byte[] bytes = this.getStringHelper().convertToBytes(hex);
return this.extractAccessToken(bytes);
}
private User extractUser(AccessToken accessToken) {
if (accessToken == null) {
return null;
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(accessToken.getGenerateTime());
calendar.add(Calendar.SECOND, accessToken.getExpiresIn());
Date expireTime = calendar.getTime();
if (expireTime.before(new Date(System.currentTimeMillis()))) {
return null;
}
return this.getUserService().getUserByName(accessToken.getUserName());
}
public AccessToken generateAccessToken(User user) {
AccessToken accessToken = new AccessToken();
accessToken.setExpiresIn(this.defaultExpiresTime);
accessToken.setGenerateTime(new Date(System.currentTimeMillis()));
accessToken.setPassword(user.getPassword());
accessToken.setUserName(user.getUserName());
// TODO: scope
accessToken.setScope(new ArrayList<String>());
accessToken.getScope().add("all");
return accessToken;
}
private AccessToken extractAccessToken(byte[] bytes) {
try {
byte[] decrypted = this.getCryptoManager().decrypt(bytes);
ObjectInputStream inputStream = new ObjectInputStream(
new ByteArrayInputStream(decrypted));
return (AccessToken) inputStream.readObject();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private String generateCredentialFromAccessToken(AccessToken accessToken) {
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutputStream stream = new ObjectOutputStream(outputStream);
stream.writeObject(accessToken);
byte[] data = outputStream.toByteArray();
byte[] encryptedData = this.getCryptoManager().encrypt(data);
return this.getStringHelper().convertToHexString(encryptedData);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}

View File

@ -0,0 +1,122 @@
package org.bench4q.master.auth;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore.PrivateKeyEntry;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Enumeration;
import javax.crypto.Cipher;
import org.springframework.stereotype.Component;
@Component
public class CryptoManager {
private static final int MAX_ENCRYPT_BLOCK = 245;
private static final int MAX_DECRYPT_BLOCK = 256;
private PublicKey publicKey;
private PrivateKey privateKey;
private PublicKey getPublicKey() {
return publicKey;
}
private void setPublicKey(PublicKey publicKey) {
this.publicKey = publicKey;
}
private PrivateKey getPrivateKey() {
return privateKey;
}
private void setPrivateKey(PrivateKey privateKey) {
this.privateKey = privateKey;
}
public CryptoManager() {
try {
String pfxFileName = Thread.currentThread().getContextClassLoader()
.getResource("key.pfx").getFile();
String pfxPassword = "123456";
File pfxFile = new File(pfxFileName);
FileInputStream pfxFileInputStream = new FileInputStream(pfxFile);
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(pfxFileInputStream, pfxPassword.toCharArray());
pfxFileInputStream.close();
Enumeration<String> aliases = keyStore.aliases();
if (aliases.hasMoreElements()) {
String alias = aliases.nextElement();
PrivateKeyEntry privateKeyEntry = (PrivateKeyEntry) keyStore
.getEntry(alias, new KeyStore.PasswordProtection(
pfxPassword.toCharArray()));
this.setPrivateKey(privateKeyEntry.getPrivateKey());
this.setPublicKey(privateKeyEntry.getCertificate()
.getPublicKey());
}
} catch (Exception e) {
e.printStackTrace();
}
}
public byte[] encrypt(byte[] data) {
try {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, this.getPublicKey());
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public byte[] decrypt(byte[] encryptedData) {
try {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, this.getPrivateKey());
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(encryptedData, offSet,
MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen
- offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}

View File

@ -0,0 +1,40 @@
package org.bench4q.master.helper;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import org.springframework.stereotype.Component;
@Component
public class HttpHelper {
public String get(String url, String accessToken) {
try {
URL target = new URL(url);
HttpURLConnection httpURLConnection = (HttpURLConnection) target
.openConnection();
httpURLConnection.setDoOutput(false);
httpURLConnection.setDoInput(true);
httpURLConnection.setUseCaches(false);
httpURLConnection.setRequestMethod("GET");
if (accessToken != null) {
httpURLConnection.setRequestProperty("Authorization", "Bearer "
+ accessToken);
}
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(httpURLConnection.getInputStream()));
int temp = -1;
StringBuffer stringBuffer = new StringBuffer();
while ((temp = bufferedReader.read()) != -1) {
stringBuffer.append((char) temp);
}
bufferedReader.close();
return stringBuffer.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}

BIN
src/main/resources/key.pfx Normal file

Binary file not shown.

View File

@ -0,0 +1,21 @@
package org.bench4q.master.test;
import org.bench4q.master.helper.HttpHelper;
import org.junit.Assert;
import org.junit.Test;
public class AuthenticationTest {
@Test
public void testAuthenticationUser() {
String accessToken = "077e228e31ee315ed9fb03d45be559a162aecc8a8c614d7538459af807387cc3d04b065d015864d91627c8c73858d734ab0eb24b3d673efd2f5f3aa518cb48b511279a712c85cf8b84dabb32be6060fce1f077ff12818af870315fa03dafcb7618d8e87f98f1971abe569303a40d59aa3803d95c6b5a7dc42a22afee8a169b455e65dd56f8e035dd2549d028ddf814009ae600788c19817ade14321c65cc9f64dfc38000e6087e6423843a9af0cb2d3120f680a6f6e441f8b244d592b7390063a86587570180b5d4689eecf8480cfa37214adfe9f95a2b4deae6a96a3f4a3542e04f32c0493e8b8b23fe5220bb3c01a726b5274884631df61824c47d77d6d70d666aeb043da4f6e6697d7492b8965ac91ceeeb5fc324152a1c70a53ca74834672d526618f6cea2c4b3945b3117d95836e7d52c1756e6ed302d6c1d048ff9834e01ffb84b9ff3f99cc6d140b0dfc342820c291b7d0469581a598d214b14028684b92a131d322d979848bad864d93f5329b526f64ddb27be18f322f9837b33fefca5b7a2215c93faff5d09b21863f1f79780f78e35da6479e9484805508f1ee030b73a7d93a7ed14ed76d582faa20147a6c34a586905f712a0c1ffa25367e275887da4a7b2d6224c497a26de485d569ec67fefb907753276e234bca389496122b556d206cdf7c7a7976ee2780cdb6cf514ef71e5a8b64ab5015ef8c75b2e30fd44";
String actual = new HttpHelper().get("http://localhost:8080/",
accessToken);
Assert.assertEquals("Hello [Test]", actual);
}
@Test
public void testAuthenticationAnonymousUser() {
String actual = new HttpHelper().get("http://localhost:8080/", null);
Assert.assertEquals("Hello [Anonymous User]", actual);
}
}