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;
}
}