Java代碼實現jira單點登陸java
最近最近剛上一個項目,須要經過jira來跟蹤系統問題,客戶要求實現從他們現有門戶中單點登陸到jira系統。apache
Jira是一個款知名度比較高的商業軟件,按理應該有解決方案,因而在網上查找相關方式,發現關於jira的資料 至關少,未找到任務與第三方實現單點登陸的方式。無奈只能經過反編譯瞭解jira用戶登陸驗證的實現方式,從atlassian-seraph*.jar包內的com.atlassian.seraph.auth. DefaultAuthenticator類實現代碼,咱們瞭解jira是經過getUser來獲取用戶信息,獲取用戶信息主要分爲三步,具體以下:api
一、 從sessioncookie
二、 從cookiessession
三、 getUserFromBasicAuthenticationless
代碼片斷:測試
String METHOD = "getUser : ";ui
boolean dbg = log.isDebugEnabled();this
HttpSession session = httpServletRequest.getSession(false);debug
if (session != null)
{
Principal sessionUser = getUserFromSession(httpServletRequest);
if (sessionUser != null)
{
LoginReason.OK.stampRequestResponse(httpServletRequest, httpServletResponse);
return sessionUser;
}
}
if (!LoginReason.OUT.isStamped(httpServletRequest))
{
Principal cookieUser = getUserFromCookie(httpServletRequest, httpServletResponse);
if (cookieUser != null)
{
return cookieUser;
}
}
if (RedirectUtils.isBasicAuthentication(httpServletRequest, this.basicAuthParameterName))
{
Principal basicAuthUser = getUserFromBasicAuthentication(httpServletRequest, httpServletResponse);
if (basicAuthUser != null)
{
return basicAuthUser;
}
}
if (dbg)
{
log.debug("getUser : User not found in either Session, Cookie or Basic Auth.");
}
return null;
經過分析代碼,咱們若是要實現單點登陸只有兩種方式可選
一、 不改變原有代碼,從門戶中寫知足jira的cookie的信息,
二、 經過java代碼實現接口,
a) 實現虛擬類DefaultAuthenticator,重寫getUser方式,在jiraJiraSeraphAuthenticator類的基礎上增長第四從獲取用戶信息的方式,即:別的應用系統寫cookie(必須是採用域名的方式),jira從cookie中獲取用戶。
b) 並修改配置 文件 atlassian-jira/WEB-INF/classes/seraph-config.xml,具體修改以下:
<!-- <authenticator class="com.atlassian.jira.security.login.JiraSeraphAuthenticator"/>-->
<authenticator class="com.atlassian.jira.security.cuslogin.CusJiraSeraphAuthenticator"/>
c) 重啓jira,經測試 ,jira可以從門戶登陸。
QQ:279505686
a) 寫cookie的代碼
<%
String PORTAL_COOKIE_KEY = "JIRA_USER_NAME_KEY";
Cookie cookie=new Cookie(PORTAL_COOKIE_KEY,"admin");
cookie.setDomain("ncyc.cbpm");
cookie.setMaxAge(-1);
cookie.setPath("/");
response.addCookie(cookie);
%>
b) 獲取cookie的方式
package com.atlassian.jira.security.cuslogin;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
public class SSOnCookie {
private final String PORTAL_COOKIE_KEY = "JIRA_USER_NAME_KEY";
private HttpServletRequest request = null;
public static SSOnCookie getSSOCookie(HttpServletRequest request) {
SSOnCookie cookie = new SSOnCookie();
cookie.request = request;
return cookie;
}
public boolean isExpired() {
Cookie[] cookies = request.getCookies();
System.out.println("cookie"+cookies);
if (null == cookies || cookies.length == 0)
return true;
System.out.println("cookie length:"+cookies.length);
for (Cookie cookie : cookies) {
System.out.println("cookie name:"+cookie.getName());
if (cookie.getName().equals(PORTAL_COOKIE_KEY)) {
return false;
}
}
return true;
}
/** Return the username implied by the cookie in the request. */
public String getLoginId() {
Cookie[] cookies = request.getCookies();
if (null == cookies || cookies.length == 0)
return null;
for (Cookie cookie : cookies) {
if (cookie.getName().equals(PORTAL_COOKIE_KEY)) {
return cookie.getValue();
}
}
return null;
}
}
c) 實現單點登陸的代碼
package com.atlassian.jira.security.cuslogin;
import com.atlassian.crowd.embedded.api.CrowdService;
import com.atlassian.crowd.exception.AccountNotFoundException;
import com.atlassian.crowd.exception.FailedAuthenticationException;
import com.atlassian.crowd.exception.runtime.CommunicationException;
import com.atlassian.crowd.exception.runtime.OperationFailedException;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.user.ApplicationUser;
import com.atlassian.jira.user.util.UserManager;
import com.atlassian.seraph.auth.AuthenticationContextAwareAuthenticator;
import com.atlassian.seraph.auth.AuthenticationErrorType;
import com.atlassian.seraph.auth.AuthenticatorException;
import com.atlassian.seraph.auth.DefaultAuthenticator;
import com.atlassian.seraph.auth.LoginReason;
import com.atlassian.seraph.elevatedsecurity.ElevatedSecurityGuard;
import com.atlassian.seraph.util.SecurityUtils;
import com.atlassian.seraph.util.SecurityUtils.UserPassCredentials;
import java.io.IOException;
import java.security.Principal;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.log4j.Logger;
@AuthenticationContextAwareAuthenticator
public class CusJiraSeraphAuthenticator extends DefaultAuthenticator
{
private static final Logger log = Logger.getLogger(CusJiraSeraphAuthenticator.class);
protected Principal getUser(String username)
{
return getUserManager().getUserByName(username);
}
protected boolean authenticate(Principal user, String password)
throws AuthenticatorException
{
try
{
crowdServiceAuthenticate(user, password);
return true;
}
catch (AccountNotFoundException e)
{
log.debug("authenticate : '" + user.getName() + "' does not exist and cannot be authenticated.");
return false;
}
catch (FailedAuthenticationException e)
{
return false;
}
catch (CommunicationException ex)
{
throw new AuthenticatorException(AuthenticationErrorType.CommunicationError);
}
catch (OperationFailedException ex)
{
log.error("Error occurred while trying to authenticate user '" + user.getName() + "'.", ex);
}throw new AuthenticatorException(AuthenticationErrorType.UnknownError);
}
private void crowdServiceAuthenticate(Principal user, String password)
throws FailedAuthenticationException
{
Thread currentThread = Thread.currentThread();
ClassLoader origCCL = currentThread.getContextClassLoader();
try
{
currentThread.setContextClassLoader(getClass().getClassLoader());
getCrowdService().authenticate(user.getName(), password);
}
finally
{
currentThread.setContextClassLoader(origCCL);
}
}
protected Principal refreshPrincipalObtainedFromSession(HttpServletRequest httpServletRequest, Principal principal)
{
Principal freshPrincipal = principal;
if ((principal != null) && (principal.getName() != null))
{
if ((principal instanceof ApplicationUser))
{
freshPrincipal = getUserManager().getUserByKey(((ApplicationUser)principal).getKey());
}
else
{
freshPrincipal = getUser(principal.getName());
}
putPrincipalInSessionContext(httpServletRequest, freshPrincipal);
}
return freshPrincipal;
}
protected Principal getUserFromBasicAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
{
String METHOD = "getUserFromSession : ";
boolean dbg = log.isDebugEnabled();
String header = httpServletRequest.getHeader("Authorization");
LoginReason reason = LoginReason.OK;
if (SecurityUtils.isBasicAuthorizationHeader(header))
{
if (dbg)
{
log.debug("getUserFromSession : Looking in Basic Auth headers");
}
SecurityUtils.UserPassCredentials creds = SecurityUtils.decodeBasicAuthorizationCredentials(header);
ElevatedSecurityGuard securityGuard = getElevatedSecurityGuard();
if (!securityGuard.performElevatedSecurityCheck(httpServletRequest, creds.getUsername()))
{
if (dbg)
{
log.debug("getUserFromSession : '" + creds.getUsername() + "' failed elevated security check");
}
reason = LoginReason.AUTHENTICATION_DENIED.stampRequestResponse(httpServletRequest, httpServletResponse);
securityGuard.onFailedLoginAttempt(httpServletRequest, creds.getUsername());
}
else
{
if (dbg)
{
log.debug("getUserFromSession : '" + creds.getUsername() + "' does not require elevated security check. Attempting authentication...");
}
try
{
boolean loggedin = login(httpServletRequest, httpServletResponse, creds.getUsername(), creds.getPassword(), false);
if (loggedin)
{
reason = LoginReason.OK.stampRequestResponse(httpServletRequest, httpServletResponse);
securityGuard.onSuccessfulLoginAttempt(httpServletRequest, creds.getUsername());
if (dbg)
{
log.debug("getUserFromSession : Authenticated '" + creds.getUsername() + "' via Basic Auth");
}
return getUser(creds.getUsername());
}
reason = LoginReason.AUTHENTICATED_FAILED.stampRequestResponse(httpServletRequest, httpServletResponse);
securityGuard.onFailedLoginAttempt(httpServletRequest, creds.getUsername());
}
catch (AuthenticatorException e)
{
log.warn("getUserFromSession : Exception trying to login '" + creds.getUsername() + "' via Basic Auth:" + e, e);
}
}
try
{
httpServletResponse.sendError(401, "Basic Authentication Failure - Reason : " + reason.toString());
}
catch (IOException e)
{
log.warn("getUserFromSession : Exception trying to send Basic Auth failed error: " + e, e);
}
return null;
}
try
{
httpServletResponse.setHeader("WWW-Authenticate", "Basic realm=\"protected-area\"");
httpServletResponse.sendError(401);
}
catch (IOException e)
{
log.warn("getUserFromSession : Exception trying to send Basic Auth failed error: " + e, e);
}
return null;
}
private CrowdService getCrowdService()
{
return (CrowdService)ComponentAccessor.getComponent(CrowdService.class);
}
private UserManager getUserManager() {
return ComponentAccessor.getUserManager();
}
public Principal getUser(HttpServletRequest request, HttpServletResponse response)
{
Principal user = null;
try
{
user=super.getUser(request, response);
if(user== null)
{
SSOnCookie ssoCookie = SSOnCookie.getSSOCookie(request);
log.info("cus Got SSOnCookie "+ssoCookie);
if (ssoCookie != null && !ssoCookie.isExpired())
{ // Seamless login from intranet
log.info("Trying seamless Single Sign-on...");
String username = ssoCookie.getLoginId();
System.out.println("Got username = " + username);
if (username != null)
{
user = getUser(username);
if(null!=user){
log.info("Logged in via SSO, with User "+user);
request.getSession().setAttribute(DefaultAuthenticator.LOGGED_IN_KEY, user);
request.getSession().setAttribute(DefaultAuthenticator.LOGGED_OUT_KEY, null);
}else {
System.out.println("get not user");
}
}
}
else
{
log.info("SSOCookie is null; redirecting");
//user was not found, or not currently valid
return null;
}
}
}
catch (Exception e) // catch class cast exceptions
{
log.warn("Exception: " + e, e);
}
return user;
}
}