рд╕рдХреНрд░рд┐рдп рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдХреЗ рд╕рд╛рде JIRA 4.1 рдПрдХреАрдХрд░рдг

рдореБрдЭреЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╢рд░реНрддреЛрдВ рдХреЗ рд╕рд╛рде рд╕рдХреНрд░рд┐рдп рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдХреЗ рд╕рд╛рде JIRA 4.1 рдХреЛ рдПрдХреАрдХреГрдд рдХрд░рдиреЗ рдХрд╛ рдХрд╛рдо рдорд┐рд▓рд╛:
  1. рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдФрд░ рд╕рдореВрд╣ рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝реЗрд╢рди (рд╕рдВрд╕реНрдХрд░рдг 4.1 рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝реЗрд╢рди рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ)
  2. рдкрд╛рд░рджрд░реНрд╢реА рдкреНрд░рдорд╛рдгреАрдХрд░рдг (JIRA рд▓реЙрдЧрд┐рди рдХреЗ рд░реВрдк рдореЗрдВ рдИрдореЗрд▓ рдкрддреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ)
  3. рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЧреБрдгреЛрдВ рдореЗрдВ рднрд░рдирд╛ (рдлрд╝реЛрди рдирдВрдмрд░)
  4. рдЬреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ AD рдореЗрдВ рдирд╣реАрдВ рд╣реИрдВ рдЙрдиреНрд╣реЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП

рдФрд░ рдЗрд╕ рддрд░рд╣ рдореИрдВрдиреЗ рдЗрд╕реЗ рд╣рд▓ рдХрд┐рдпрд╛:


рдЦрдмреНрд░реЛрд╡рд╕реНрдХ рдирд╛рдЧрд░рд┐рдХ XoJIoD рдХреЗ рдЕрдиреБрд░реЛрдз рдкрд░ рд╡рд┐рд╖рдп рдкреНрд░рдХрд╛рд╢рд┐рдд рд╣реБрдЖ рдерд╛ - рдЗрд╕рд▓рд┐рдП рдЗрд╕рдХреЗ рд▓рд┐рдП рдкреНрд▓рд╕рд╕ рд╣реИрдВред

JIRA рд╕реЗрдЯрдЕрдк


JIRA 4.1 рдореЗрдВ LDAP рдХреЗ рд╕рд╛рде рдПрдХреАрдХрд░рдг рдХреЗ рд▓рд┐рдП рдПрдХ рддреИрдпрд╛рд░ рддрдВрддреНрд░ рд╣реИ, рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ рдПрдХ рдЪреАрдЬ рдЬреЛ рдпрд╣ рдХрд░ рд╕рдХрддреА рд╣реИ рд╡рд╣ рд╣реИ рдкрд╛рд╕рд╡рд░реНрдб рдХреА рдЬрд╛рдВрдЪ, рдЕрд░реНрдерд╛рддред рдХрд┐рд╕реА рднреА рддреБрд▓реНрдпрдХрд╛рд▓рди рдХреА рдмрд╛рдд рдирд╣реАрдВ рд╣реИред рдЖрдк рдЗрд╕ рдЪрд░рдг рдХреЛ рдЫреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рднрд╡рд┐рд╖реНрдп рдореЗрдВ, рд╣рдо SPNEGO рдкрд╛рд╕рд╡рд░реНрдб рд╕рддреНрдпрд╛рдкрди рд╕реМрдВрдкреЗрдВрдЧреЗред

рдЗрд╕рд▓рд┐рдП, рд╣рдо рдкреНрд░рд╢рд╛рд╕рдХ рдЦрд╛рддреЗ рдХреЗ рддрд╣рдд JIRA рдореЗрдВ рдЬрд╛рддреЗ рд╣реИрдВ рдФрд░ рдкреНрд░рд╢рд╛рд╕рди тЖТ рд╕рд┐рд╕реНрдЯрдо тЖТ LDAP рд╕реЗрдХреНрд╢рди рдореЗрдВ рдЬрд╛рддреЗ рд╣реИрдВ рдФрд░ рдлреЙрд░реНрдо рднрд░рддреЗ рд╣реИрдВ:
рдЫрд╡рд┐
рдХрд╣рд╛рдВ:


рдпрджрд┐ рдЖрдкрдХреЛ PartialResultException рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рдкреНрд░рд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдЧреНрд▓реЛрдмрд▓ рдХреИрдЯрд▓реЙрдЧ рдкреЛрд░реНрдЯ (3268) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред рдпрджрд┐ рд╕рдм рдХреБрдЫ рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рднрд░рд╛ рдЧрдпрд╛ рд╣реИ, рддреЛ LDAP рдкреНрд░рдорд╛рдгреАрдХрд░рдг рд╕рдлрд▓ рд╕рдВрджреЗрд╢ рджрд┐рдЦрд╛рдИ рджреЗрдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рдиреАрдЪреЗ, рдПрдХреАрдХрд░рдг рдХреЗ рд▓рд┐рдП XML рдлрд╝рд╛рдЗрд▓ рдХреА рд╕рд╛рдордЧреНрд░реАред рдЗрд╕реЗ рдХреЙрдкреА рдХрд░реЗрдВ, JIRA рд╕рд░реНрд╡рд░ рдХреЛ рдмрдВрдж рдХрд░реЗрдВ рдФрд░ рдЗрд╕ рд╕рд╛рдордЧреНрд░реА рдХреЗ рд╕рд╛рде рдмрджрд▓реЗрдВ рдЬреЛ $ JIRA_HOME / atlassian-jira / WEB-INF / classes / osuser.xml рдореЗрдВ рдереА ред рдЗрд╕ рдЕрд╡рд╕рд░ рдХреЛ рд▓реЗрддреЗ рд╣реБрдП, рд╣рдо рдЬреЗрд▓реА рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЛ рднреА рд╕рдХреНрд╖рдо рдХрд░рддреЗ рд╣реИрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, $ JIRA_HOME / bin / setenv.sh рдлрд╝рд╛рдЗрд▓ (рд▓рд┐рдирдХреНрд╕ рдХреЗ рд▓рд┐рдП) рдореЗрдВ, JAVA_OPTS рдкреИрд░рд╛рдореАрдЯрд░ рдореЗрдВ -Djira.jelly.on = true рд▓рд╛рдЗрди рдЬреЛрдбрд╝реЗрдВред

рдЙрд╕рдХреЗ рдмрд╛рдж, JIRA рдХреЛ рдлрд┐рд░ рд╕реЗ рдЪрд▓рд╛рдПрдВ рдФрд░ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ AD рдХреЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╡рд╣рд╛рдВ рд╕реЗ рдкрд╛рд╕рд╡рд░реНрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВред

рдПрдХ рдЬреЗрд▓реА рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдмрдирд╛рдПрдБ


рдореИрдВрдиреЗ рдПрдХ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдпрдХреНрд░рдо рд▓рд┐рдЦрд╛ рдерд╛ рдЬреЛ рдмрд╣реБрдд рд╢реБрд░реБрдЖрдд рдореЗрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдФрд░ рд╕рдореВрд╣реЛрдВ рдХреЛ рдмрдирд╛рддрд╛ рд╣реИ, рдФрд░ рдлрд┐рд░ рдЗрд╕реЗ рдлреЗрдВрдХрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рджрдпрд╛ рдереАред рдЗрд╕рд▓рд┐рдП, рдпрджрд┐ рдЖрдк рдкреНрд░рдорд╛рдгрдХ рдпрд╛ рд╕реЗрд╡рд╛ (рдиреАрдЪреЗ рджреЗрдЦреЗрдВ) рдореЗрдВ рд╕рдореВрд╣ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдЗрд╕ рдЪрд░рдг рдХреЛ рдЫреЛрдбрд╝ рднреА рд╕рдХрддреЗ рд╣реИрдВред

Atlassian рд╡реЗрдмрд╕рд╛рдЗрдЯ рдкрд░ рдкреНрд░рд▓реЗрдЦрди рдореЗрдВ рдПрдХ рдУрдкрди рд╕реЛрд░реНрд╕ рдпреВрдЯрд┐рд▓рд┐рдЯреА рдкрд╛рдИ рдЧрдИ рдЬреЛ рдПрдХ Jelly рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдмрдирд╛рддреА рд╣реИ рдЬреЛ JIRA рдореЗрдВ LDAP рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдмрдирд╛рддреА рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдореБрдЭреЗ рд╕рдореВрд╣ рдмрдирд╛рдиреЗ рдХреА рднреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдереА, рдЗрд╕рд▓рд┐рдП, рдЬреЗрд▓реА рдЯреИрдЧ рдкрд░ рдкреНрд░рд▓реЗрдЦрди рд╕реЗ рд▓реИрд╕, рдореИрдВрдиреЗ рдЗрд╕ рд░рд╛рдЬреНрдп рдореЗрдВ рдЗрд╕ рдЙрдкрдпреЛрдЧрд┐рддрд╛ рдХреЛ рдЬреЛрдбрд╝рд╛:
import java.io.File; import java.io.FileReader; import java.util.Properties; import java.util.Random; import javax.naming.NamingEnumeration; import javax.naming.directory.*; import org.apache.commons.lang3.StringEscapeUtils; public class LDAPImporter { public static void main(String[] args) throws Exception { Properties properties = new Properties(); File path = new File(LDAPImporter.class.getProtectionDomain() .getCodeSource().getLocation().toURI()); if (!path.isDirectory()) { path = path.getParentFile(); } properties.load(new FileReader(new File(path, "LDAP.properties"))); properties.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory"); DirContext groupContext = new InitialDirContext(properties); SearchControls groupControls = new SearchControls(); groupControls.setReturningAttributes(new String[] { (String) properties.get("groupNameAttribute"), (String) properties.get("groupDNAttribute") }); groupControls.setSearchScope(SearchControls.SUBTREE_SCOPE); System.out.println("<JiraJelly xmlns:jira=\"jelly:com.atlassian.jira.jelly.JiraTagLib\">\n"); NamingEnumeration results = groupContext.search( (String) properties.get("baseDN"), (String) properties.get("groupFilter"), groupControls); //    (Organisation Unit') while (results != null && results.hasMoreElements()) { SearchResult result = (SearchResult) results.next(); Attribute attribute = result.getAttributes().get( (String) properties.get("groupNameAttribute")); if (attribute == null) { continue; } String groupName = (String) attribute.get(); String groupDN = (String) result.getAttributes() .get((String) properties.get("groupDNAttribute")).get(); //   System.out.println("<jira:CreateGroup group-name=\"" + StringEscapeUtils.escapeXml("[AD] " + groupName) + "\"/>\n"); DirContext userContext = new InitialDirContext(properties); SearchControls userControls = new SearchControls(); userControls.setReturningAttributes(new String[] { (String) properties.get("userLoginAttribute"), (String) properties.get("userNameAttribute"), (String) properties.get("userMailAttribute") }); userControls.setSearchScope(SearchControls.ONELEVEL_SCOPE); NamingEnumeration users = userContext.search(groupDN, (String) properties.get("userFilter"), userControls); //      while (users != null && users.hasMoreElements()) { SearchResult user = (SearchResult) users.next(); attribute = user.getAttributes().get( (String) properties.get("userLoginAttribute")); if (attribute == null) { continue; } String userLogin = (String) attribute.get(); attribute = user.getAttributes().get( (String) properties.get("userNameAttribute")); String userName; if (attribute != null) { userName = (String) attribute.get(); } else { userName = userLogin; } attribute = user.getAttributes().get( (String) properties.get("userMailAttribute")); String userMail; if (attribute != null) { userMail = (String) attribute.get(); } else { userMail = userLogin.replace(' ', '.') + '@' + properties.get("userMailDomain"); } /* * ..     AD, *    */ String password = Integer.toHexString(new Random().nextInt()); //   System.out.println("<jira:CreateUser username=\"" + StringEscapeUtils.escapeXml(userLogin.toLowerCase()) + "\" password=\"" + password + "\" confirm=\"" + password + "\" fullname=\"" + StringEscapeUtils.escapeXml(userName) + "\" email=\"" + StringEscapeUtils.escapeXml(userMail) + "\"/>\n"); //     System.out.println("<jira:AddUserToGroup username=\"" + StringEscapeUtils.escapeXml(userLogin.toLowerCase()) + "\" group-name=\"" + StringEscapeUtils.escapeXml("[AD] " + groupName) + "\"/>\n"); } } System.out.println("</JiraJelly>"); } } 

рд╕реЗрдЯрд┐рдВрдЧреНрд╕ LDAP.properties рдлрд╝рд╛рдЗрд▓ рд╕реЗ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреЗ рд╕рдорд╛рди рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рд╕реНрдерд┐рдд рд╣реИрдВ, рдпрд╣ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:
 #   LDAP java.naming.provider.url=ldap://127.0.0.1:389 # DN    java.naming.security.principal=cn=test,ou=users,dc=local,dc=domain #   java.naming.security.credentials=password #  DN baseDN=ou=users,dc=local,dc=domain #     groupNameAttribute=name #   DN  groupDNAttribute=distinguishedName #   groupFilter=(objectclass=organizationalUnit) #     userLoginAttribute=mail #     (  ,  ) userNameAttribute=displayName #    e-mail  (  ,   + @ +  ) userMailAttribute=mail #   userMailDomain=local.domain #   userFilter=(objectclass=user) 

рдЗрд╕ рддрд░рд╣ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рдкреНрд░рд╢рд╛рд╕рди рдореЗрдВ рдЬреАрд░рд╛ рдХреЛ рдЦрд┐рд▓рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ тЖТ рд╡рд┐рдХрд▓реНрдк рдФрд░ рд╕реЗрдЯрд┐рдВрдЧреНрд╕ тЖТ рдЬреЗрд▓реА рдзрд╛рд╡рдХ рдЕрдиреБрднрд╛рдЧ, рдФрд░ рд╡рд╣ рдереЛрдбрд╝рд╛ рд╡рд┐рдЪрд╛рд░ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдФрд░ рд╕рдореВрд╣ рдмрдирд╛рддреА рд╣реИред

рдкрд╛рд░рджрд░реНрд╢реА рдкреНрд░рдорд╛рдгреАрдХрд░рдг


рдкрд╛рд░рджрд░реНрд╢реА рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдХрд╛ рд╡рд┐рдЪрд╛рд░ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ: SPNEGO рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдкреНрд░рдорд╛рдгрд┐рдд рдХрд░рддрд╛ рд╣реИ рдФрд░ REMOTE USER рдЪрд░ рдореЗрдВ JIRA рдХреЛ рдкрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд▓реЙрдЧ рдЗрди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо рд╣реИред рдирдХрд╛рд░рд╛рддреНрдордХ рдкрдХреНрд╖ рдпрд╣ рд╣реИ рдХрд┐ рдЗрд╕ рдпреЛрдЬрдирд╛ рдХреЗ рд╕рд╛рде , рдЬреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ AD рдореЗрдВ рдирд╣реАрдВ рд╣реИрдВ , рд╡реЗ JIRA рдореЗрдВ рдкреНрд░рд╡реЗрд╢ рдирд╣реАрдВ рдХрд░ рдкрд╛рдПрдВрдЧреЗ , рд▓реЗрдХрд┐рди рдореИрдВрдиреЗ рдХреБрдЫ рднреА рдмреЗрд╣рддрд░ рдирд╣реАрдВ рд╕реЛрдЪрд╛ред

SPNEGO

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, SPNEGO рдХреЗ рдкреНрд░рджрд░реНрд╢рди рдХреА рдЬрд╛рдБрдЪ рдХрд░реЗрдВ ред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рддреАрди рдлрд╝рд╛рдЗрд▓реЗрдВ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ: krb5.conf , login.conf рдФрд░ HelloKDC.java ред
[Libdefaults] рдЕрдиреБрднрд╛рдЧ рдореЗрдВ krb5.conf рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдПрдХ рдкрдВрдХреНрддрд┐ рдЧрд╛рдпрдм рд╣реИ, рдЗрд╕реЗ рджрд░реНрдЬ рдХрд░рдирд╛ рди рднреВрд▓реЗрдВред рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдмрджрд▓рдиреЗ рдХреЗ рдмрд╛рдж, krb5.conf рдлрд╝рд╛рдЗрд▓ рдХреЛ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП:
 [libdefaults] default_realm = LOCAL.DOMAIN default_tkt_enctypes = aes128-cts rc4-hmac des3-cbc-sha1 des-cbc-md5 des-cbc-crc default_tgs_enctypes = aes128-cts rc4-hmac des3-cbc-sha1 des-cbc-md5 des-cbc-crc permitted_enctypes = aes128-cts rc4-hmac des3-cbc-sha1 des-cbc-md5 des-cbc-crc [realms] LOCAL.DOMAIN = { kdc = dc5.local.domain default_domain = LOCAL.DOMAIN } [domain_realm] .LOCAL.DOMAIN = LOCAL.DOMAIN 

HelloKDC.java:
 ... // Domain (pre-authentication) account final String username = "test"; // Password for the pre-auth acct. final String password = "password"; // Name of our krb5 config file final String krbfile = "krb5.conf"; // Name of our login config file final String loginfile = "login.conf"; // Name of our login module final String module = "spnego-client"; ... 

рдлрд╝рд╛рдЗрд▓ рдХреЛ рд╕рдВрдХрд▓рд┐рдд рдХрд░реЗрдВ рдФрд░ рдЪрд▓рд╛рдПрдВ HelloKDC.java, рдЕрдЧрд░ рд╕рдм рдХреБрдЫ рдареАрдХ рд╣реЛ рдЧрдпрд╛, рддреЛ рдпрд╣ рд▓рд╛рдЗрдиреЛрдВ рдХрд╛ рдПрдХ рдЧреБрдЪреНрдЫрд╛ рдкреНрд░рд┐рдВрдЯ рдХрд░реЗрдЧрд╛ рдФрд░ рдХрдиреЗрдХреНрд╢рди рдкрд░реАрдХреНрд╖рдг рдХреЗ рдЕрдВрдд рдореЗрдВ рд╕рдлрд▓ рд╣реЛрдЧрд╛ред

рдЕрдЧрд▓рд╛, рд╕рдорд░реНрдерди рдЙрдкрдХрд░рдг рдЙрдкрдпреЛрдЧрд┐рддрд╛ рд╕реЗрдЯ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ, рдЙрдиреНрд╣реЗрдВ рд╡реНрдпрд╡рд╕реНрдерд╛рдкрдХ рдХреЗ рдбреЛрдореЗрди рдХрдВрдкреНрдпреВрдЯрд░ рдкрд░ рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВ рдФрд░ рдХрдорд╛рдВрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдВ:
 setspn.exe -A HTTP/domain1 test setspn.exe -A HTTP/domain2 test ... setspn.exe -A HTTP/domainN test 

рдЬрд╣рд╛рдБ

SPNEGO рд╡рд┐рддрд░рдг рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ рдФрд░ рдЗрд╕реЗ $ JIRA_HOME / lib рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рдбрд╛рд▓реЗрдВ ред $ JIRA_HOME / conf / web.xml рдлрд╝рд╛рдЗрд▓ рдЦреЛрд▓реЗрдВ рдФрд░ рдЕрдВрдд рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд▓рд╛рдЗрдиреЗрдВ рдЬреЛрдбрд╝реЗрдВ (рд▓реЗрдХрд┐рди рд╡реЗрдм-рдРрдк рдЯреИрдЧ рдмрдВрдж рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ):
 <filter> <filter-name>SpnegoHttpFilter</filter-name> <filter-class>net.sourceforge.spnego.SpnegoHttpFilter</filter-class> <init-param> <param-name>spnego.allow.basic</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>spnego.allow.localhost</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>spnego.allow.unsecure.basic</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>spnego.login.client.module</param-name> <param-value>spnego-client</param-value> </init-param> <init-param> <param-name>spnego.krb5.conf</param-name> <param-value>krb5.conf</param-value> </init-param> <init-param> <param-name>spnego.login.conf</param-name> <param-value>login.conf</param-value> </init-param> <init-param> <param-name>spnego.preauth.username</param-name> <param-value>test</param-value> </init-param> <init-param> <param-name>spnego.preauth.password</param-name> <param-value>password</param-value> </init-param> <init-param> <param-name>spnego.login.server.module</param-name> <param-value>spnego-server</param-value> </init-param> <init-param> <param-name>spnego.prompt.ntlm</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>spnego.logger.level</param-name> <param-value>1</param-value> </init-param> </filter> <filter-mapping> <filter-name>SpnegoHttpFilter</filter-name> <url-pattern>*</url-pattern> </filter-mapping> 

рдЕрдкрдиреЗ рдпреВрдЬрд╝рд░рдиреЗрдо рдФрд░ рдкрд╛рд╕рд╡рд░реНрдб рдХреЛ рдЕрдкрдиреЗ рд╕рд╛рде рдмрджрд▓рдирд╛ рдпрд╛рдж рд░рдЦреЗрдВред

рдкреНрд░рдорд╛рдгрдХ

рдПрдХ рдкреНрд░рдорд╛рдг рдкрддреНрд░ рд▓рд┐рдЦрдиреЗ рдХрд╛ рд╕рдордп рдЖ рдЧрдпрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдХрд╛рд░реНрдп SPNEGO рд╕реЗ рд▓реЙрдЧ-рдЗрди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХрд╛ рд▓реЙрдЧрд┐рди рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рд╣реИ, рдЗрд╕ рд▓реЙрдЧрд┐рди рдореЗрдВ рдПрдХ рдореЗрд▓ рдбреЛрдореЗрди рдЬреЛрдбрд╝реЗрдВ (рдЪреВрдВрдХрд┐ рдИрдореЗрд▓ рдкрддреЗ JIRA рд▓реЙрдЧрд┐рди рд╣реИрдВ) рдФрд░ рдЙрди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдлреЛрди рдпреБрдХреНрдд рд╕рдВрдкрддреНрддрд┐ рдореЗрдВ рднрд░реЗрдВ рдЬрд┐рдирдХреЗ рдкрд╛рд╕ рдпрд╣ рд╕рдВрдкрддреНрддрд┐ рдирд╣реАрдВ рд╣реИ ред JIRA 4.x рдкреНрд▓рдЧрдЗрдиреНрд╕ рдХреЗ рд▓рд┐рдП SDK рдореЗрдВ JiraOsUserAuthenticatorator рд╡рд░реНрдЧ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдЬрдЧрд╣ рдирд╣реАрдВ рдереА, рдЬрд┐рд╕рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╣рдорд╛рд░реЗ рдкреНрд░рдорд╛рдгрдХ рдХреЛ рд▓рд┐рдЦрд╛ рдЬрд╛рдПрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╡рд░реНрдЧ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкрджрд╛рд╡рдирдд рд╣реИред рдЗрд╕рд▓рд┐рдП, рдЗрд╕реЗ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рд╕рдВрдХрд▓рди рдХреЗ рджреМрд░рд╛рди рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЖрдк рдЗрд╕реЗ $ JIRA_HOME / atlassian-jira / WEB-INF / classes / com / atlassian / jira / security / login / рдореЗрдВ рд▓реЗ рд╕рдХрддреЗ рд╣реИрдВ ред

рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдкреНрд░рд╛рдорд╛рдгрд┐рдХ рдХреЛрдб:
 import java.security.Principal; import java.util.Properties; import java.util.Random; import javax.naming.NamingEnumeration; import javax.naming.directory.Attribute; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.atlassian.core.user.preferences.Preferences; import com.atlassian.jira.ComponentManager; import com.atlassian.jira.security.login.JiraOsUserAuthenticator; import com.atlassian.jira.user.preferences.UserPreferencesManager; import com.atlassian.jira.user.util.UserUtil; import com.opensymphony.user.Group; import com.opensymphony.user.User; @SuppressWarnings("deprecation") public class RemoteAuthenticator extends JiraOsUserAuthenticator { private static final long serialVersionUID = 1L; private UserPreferencesManager preferencesManager = ComponentManager .getInstance().getUserPreferencesManager(); //   LDAP private final String ADDRESS_NAME = "java.naming.provider.url"; private final String ADDRESS_VALUE = "ldap://127.0.0.1:389"; // DN    private final String LOGIN_NAME = "java.naming.security.principal"; private final String LOGIN_VALUE = "cn=test,ou=users,dc=local,dc=domain"; //   private final String PASSWORD_NAME = "java.naming.security.credentials"; private final String PASSWORD_VALUE = "password"; //  DN private final String BASEDN = "ou=users,dc=local,dc=domain"; //   private final String LOGIN_ATTRIBUTE = "mail"; //   (  ,  ) private final String NAME_ATTRIBUTE = "displayName"; //    (  , //   + @ +  ) private final String MAIL_ATTRIBUTE = "mail"; //   private final String PHONE_ATTRIBUTE = "telephoneNumber"; //   private final String DOMAIN = "local.domain"; @Override public Principal getUser(HttpServletRequest request, HttpServletResponse response) { Principal user = null; if (request.getSession() != null && request.getSession(). getAttribute(JiraOsUserAuthenticator.LOGGED_IN_KEY) != null) { //    user = (Principal) request.getSession().getAttribute( JiraOsUserAuthenticator.LOGGED_IN_KEY); } else { String remote = request.getRemoteUser(); if (remote != null) { //    SPNEGO if (!remote.endsWith('@' + DOMAIN)) { /* *     , *    . *      , *      */ remote += '@' + DOMAIN; } user = getUser(remote.toLowerCase()); if (user == null) { /* *       JIRA, *  */ try { user = createUser(remote.toLowerCase()); } catch (Exception exception) { exception.printStackTrace(System.err); } } else { Preferences preferences = preferencesManager .getPreferences((User) user); String phone = preferences .getString(UserUtil.META_PROPERTY_PREFIX + "mobile"); if (phone == null || phone.isEmpty()) { /* *       , *  */ try { phone = getPhone(remote.toLowerCase()); if (phone != null) { preferences.setString( UserUtil.META_PROPERTY_PREFIX + "mobile", phone); } } catch (Exception exception) { exception.printStackTrace(System.err); } } } request.getSession().setAttribute( JiraOsUserAuthenticator.LOGGED_IN_KEY, user); request.getSession().setAttribute( JiraOsUserAuthenticator.LOGGED_OUT_KEY, null); } } return user; } private User createUser(String login) throws Exception { DirContext context = null; try { Properties properties = new Properties(); properties.put(ADDRESS_NAME, ADDRESS_VALUE); properties.put(LOGIN_NAME, LOGIN_VALUE); properties.put(PASSWORD_NAME, PASSWORD_VALUE); properties.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory"); ComponentManager componentManager = ComponentManager.getInstance(); UserUtil userUtil = componentManager.getUserUtil(); context = new InitialDirContext(properties); SearchControls controls = new SearchControls(); controls.setReturningAttributes(new String[] { "distinguishedName", NAME_ATTRIBUTE, MAIL_ATTRIBUTE, PHONE_ATTRIBUTE }); controls.setSearchScope(SearchControls.SUBTREE_SCOPE); NamingEnumeration users = context.search(BASEDN, '(' + LOGIN_ATTRIBUTE + '=' + login + ')', controls); if (users != null && users.hasMoreElements()) { /* *     ( ) *   AD */ SearchResult result = (SearchResult) users.next(); Attribute attribute = result.getAttributes() .get(NAME_ATTRIBUTE); String userName; if (attribute != null) { userName = (String) attribute.get(); } else { userName = login; } attribute = result.getAttributes().get(MAIL_ATTRIBUTE); String userMail; if (attribute != null) { userMail = (String) attribute.get(); } else { userMail = login.replace(' ', '.') + '@' + DOMAIN; } attribute = result.getAttributes().get(PHONE_ATTRIBUTE); String userPhone = null; if (attribute != null) { userPhone = ((String) attribute.get()).replace("(", "") .replace(")", ""); } String userDN = (String) result.getAttributes() .get("distinguishedName").get(); //    String userPassword = Integer.toHexString(new Random().nextInt()); //   User user = userUtil.createUserNoEvent(login, userPassword, userMail, userName); //   AD  ,   if (userPhone != null) { preferencesManager.getPreferences(user).setString( UserUtil.META_PROPERTY_PREFIX + "mobile", userPhone); } /* *     JIRA,   AD, *    */ int index = userDN.indexOf("OU=") + 3; String groupName = "[AD] " + userDN.substring(index, userDN.indexOf(',', index)); Group group = userUtil.getGroup(groupName); if (group != null) { userUtil.addUserToGroup(group, user); } return user; } else { return null; } } finally { if (context != null) { context.close(); } } } private String getPhone(String username) throws Exception { DirContext context = null; try { Properties properties = new Properties(); properties.put(ADDRESS_NAME, ADDRESS_VALUE); properties.put(LOGIN_NAME, LOGIN_VALUE); properties.put(PASSWORD_NAME, PASSWORD_VALUE); properties.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory"); context = new InitialDirContext(properties); SearchControls controls = new SearchControls(); controls.setReturningAttributes(new String[] { PHONE_ATTRIBUTE }); controls.setSearchScope(SearchControls.SUBTREE_SCOPE); NamingEnumeration users = context.search(BASEDN, '(' + LOGIN_ATTRIBUTE + '=' + username + ')', controls); if (users != null && users.hasMoreElements()) { SearchResult result = (SearchResult) users.next(); Attribute attribute = result.getAttributes().get( PHONE_ATTRIBUTE); String userPhone = null; if (attribute != null) { userPhone = ((String) attribute.get()).replace("(", "") .replace(")", ""); } return userPhone; } else { return null; } } finally { if (context != null) { context.close(); } } } } 

рд╕рдВрдХрд▓рди рдХрд░реЗрдВ, $ JIRA_HOME / atlassian-jira / WEB-INF / classes рдореЗрдВ рдбрд╛рд▓реЗрдВ, $ JIRA_HOME / atlassian-jira / WEB-INF / classes / seraph-config / .xml рдлрд╝рд╛рдЗрд▓ рдЦреЛрд▓реЗрдВ рдФрд░ рдЗрд╕рдореЗрдВ рд▓рд╛рдЗрди рдмрджрд▓реЗрдВ
 <authenticator class="com.atlassian.jira.security.login.JiraOsUserAuthenticator"/> 

рдкрд░
 <authenticator class="RemoteAuthenticator"/> 


рдЙрд╕рдХреЗ рдмрд╛рдж, рдЖрдк JIRA рдХреЛ рдкреБрдирдГ рдЖрд░рдВрдн рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЕрдкрдиреЗ рдкрд╕рдВрджреАрджрд╛ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ Kerberos рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдЧреИрд░-рдбреЛрдореЗрди рдХрдВрдкреНрдпреВрдЯрд░реЛрдВ рдХреЗ рд▓рд┐рдП, рдПрдХ BASIC рдкреНрд░рд╛рдзрд┐рдХрд░рдг рд╡рд┐рдВрдбреЛ рджрд┐рдЦрд╛рдИ рджреЗрдиреА рдЪрд╛рд╣рд┐рдП, рддрд╛рдХрд┐ рд╡реЗ рднреА рд▓реЙрдЧ рдЗрди рдХрд░ рд╕рдХреЗрдВ (рдпрджрд┐ рдЙрдирдХреЗ рдкрд╛рд╕ AD рдореЗрдВ рдЦрд╛рддреЗ рд╣реИрдВ)ред

рджрдлреНрддрд░


рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдПрдХ рд╕реЗрд╡рд╛ рдХреЛ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рдерд╛ рдХрд┐ рд╕рдордп-рд╕рдордп рдкрд░ AD рдФрд░ JIRA рдореЗрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рдирд╛рдо рдореЗрдВ рдПрдХ рдкрд╛рда рд▓реЗрдмрд▓ рдЬреЛрдбрд╝рддрд╛ рд╣реИ рдЬреЛ AD рдореЗрдВ рдирд╣реАрдВ рд╣реИрдВред рдпрд╣рд╛рдБ рдЙрд╕рдХрд╛ рдХреЛрдб рд╣реИ:
 import java.util.Map; import java.util.Properties; import java.util.Random; import javax.naming.NamingEnumeration; import javax.naming.directory.Attribute; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; import com.atlassian.configurable.ObjectConfiguration; import com.atlassian.configurable.ObjectConfigurationException; import com.atlassian.core.user.preferences.Preferences; import com.atlassian.jira.ComponentManager; import com.atlassian.jira.event.user.UserEventType; import com.atlassian.jira.service.AbstractService; import com.atlassian.jira.user.preferences.UserPreferencesManager; import com.atlassian.jira.user.util.UserUtil; import com.opensymphony.module.propertyset.PropertySet; import com.opensymphony.user.Group; import com.opensymphony.user.User; @SuppressWarnings("deprecation") public class Importer extends AbstractService implements ObjectConfiguration { //   LDAP private final String ADDRESS_NAME = "java.naming.provider.url"; private String ADDRESS_VALUE = "ldap://127.0.0.1:389"; // DN    private final String LOGIN_NAME = "java.naming.security.principal"; private String LOGIN_VALUE = "cn=test,ou=users,dc=local,dc=domain"; //   private final String PASSWORD_NAME = "java.naming.security.credentials"; private String PASSWORD_VALUE = "password"; //  DN private final String BASE_NAME = "baseDN"; private String BASE_VALUE = "ou=users,dc=local,dc=domain"; //   private final String LOGIN_ATTR_NAME = "userLoginAttribute"; private String LOGIN_ATTR_VALUE = "mail"; //   (  ,  ) private final String NAME_ATTR_NAME = "userNameAttribute"; private String NAME_ATTR_VALUE = "displayName"; //    (  ,   + @ +  // ) private final String MAIL_ATTR_NAME = "userMailAttribute"; private String MAIL_ATTR_VALUE = "mail"; //   private final String PHONE_ATTR_NAME = "userPhoneAttribute"; private String PHONE_ATTR_VALUE = "telephoneNumber"; //   private final String DOMAIN_NAME = "userMailDomain"; private String DOMAIN_VALUE = "local.domain"; //   private final String FILTER_NAME = "userFilter"; private String FILTER_VALUE = "(objectClass=user)"; // ,     private final String FIRED_STRING_NAME = "firedString"; private String FIRED_STRING_VALUE = "z_fired"; @Override public void init(PropertySet properties) throws ObjectConfigurationException { super.init(properties); for (Object keyObject : properties.getKeys()) { String key = (String) keyObject; if (key.equals(ADDRESS_NAME)) { ADDRESS_VALUE = properties.getString(key); } else if (key.equals(LOGIN_NAME)) { LOGIN_VALUE = properties.getString(key); } else if (key.equals(PASSWORD_NAME)) { PASSWORD_VALUE = properties.getString(key); } else if (key.equals(BASE_NAME)) { BASE_VALUE = properties.getString(key); } else if (key.equals(NAME_ATTR_NAME)) { NAME_ATTR_VALUE = properties.getString(key); } else if (key.equals(LOGIN_ATTR_NAME)) { LOGIN_ATTR_VALUE = properties.getString(key); } else if (key.equals(MAIL_ATTR_NAME)) { MAIL_ATTR_VALUE = properties.getString(key); } else if (key.equals(PHONE_ATTR_NAME)) { PHONE_ATTR_VALUE = properties.getString(key); } else if (key.equals(DOMAIN_NAME)) { DOMAIN_VALUE = properties.getString(key); } else if (key.equals(FILTER_NAME)) { FILTER_VALUE = properties.getString(key); } else { FIRED_STRING_VALUE = properties.getString(key); } } } @Override public ObjectConfiguration getObjectConfiguration() throws ObjectConfigurationException { return this; } @Override public void run() { try { importUsers(); checkUsers(); } catch (Exception exception) { exception.printStackTrace(); } } //    AD   JIRA private void importUsers() throws Exception { DirContext context = null; try { Properties properties = new Properties(); properties.put(ADDRESS_NAME, ADDRESS_VALUE); properties.put(LOGIN_NAME, LOGIN_VALUE); properties.put(PASSWORD_NAME, PASSWORD_VALUE); properties.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory"); ComponentManager componentManager = ComponentManager.getInstance(); UserPreferencesManager preferencesManager = componentManager .getUserPreferencesManager(); UserUtil userUtil = componentManager.getUserUtil(); context = new InitialDirContext(properties); SearchControls controls = new SearchControls(); controls.setReturningAttributes(new String[] { "distinguishedName", LOGIN_ATTR_VALUE, NAME_ATTR_VALUE, MAIL_ATTR_VALUE, PHONE_ATTR_VALUE }); controls.setSearchScope(SearchControls.SUBTREE_SCOPE); NamingEnumeration users = context.search(BASE_VALUE, FILTER_VALUE, controls); while (users != null && users.hasMoreElements()) { SearchResult result = (SearchResult) users.next(); Attribute attribute = result.getAttributes().get( LOGIN_ATTR_VALUE); if (userUtil.getUser((String) attribute.get()) != null) { //     JIRA continue; } String login = ((String) attribute.get()).toLowerCase(); attribute = result.getAttributes().get(NAME_ATTR_VALUE); String userName; if (attribute != null) { userName = (String) attribute.get(); } else { userName = login; } attribute = result.getAttributes().get(MAIL_ATTR_VALUE); String userMail; if (attribute != null) { userMail = (String) attribute.get(); } else { userMail = login.replace(' ', '.') + '@' + DOMAIN_VALUE; } attribute = result.getAttributes().get(PHONE_ATTR_VALUE); String userPhone = null; if (attribute != null) { userPhone = ((String) attribute.get()).replace("(", "") .replace(")", ""); } String userDN = (String) result.getAttributes() .get("distinguishedName").get(); //    String userPassword = Integer.toHexString(new Random() .nextInt()); //   User user = userUtil.createUserWithEvent(login, userPassword, userMail, userName, UserEventType.USER_CREATED); if (userPhone != null) { preferencesManager.getPreferences(user).setString( UserUtil.META_PROPERTY_PREFIX + "mobile", userPhone); } /* *     JIRA, *   AD,    */ int index = userDN.indexOf("OU=") + 3; String groupName = "[AD] " + userDN.substring(index, userDN.indexOf(',', index)); Group group = userUtil.getGroup(groupName); if (group != null) { userUtil.addUserToGroup(group, user); } } } finally { if (context != null) { context.close(); } } } //     ,    AD private void checkUsers() throws Exception { DirContext context = null; try { Properties properties = new Properties(); properties.put(ADDRESS_NAME, ADDRESS_VALUE); properties.put(LOGIN_NAME, LOGIN_VALUE); properties.put(PASSWORD_NAME, PASSWORD_VALUE); properties.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory"); ComponentManager componentManager = ComponentManager.getInstance(); UserPreferencesManager preferencesManager = componentManager .getUserPreferencesManager(); UserUtil userUtil = componentManager.getUserUtil(); context = new InitialDirContext(properties); SearchControls controls = new SearchControls(); controls.setReturningAttributes(new String[] { PHONE_ATTR_VALUE }); controls.setSearchScope(SearchControls.SUBTREE_SCOPE); for (User user : userUtil.getAllUsers()) { NamingEnumeration users = context.search(BASE_VALUE, "(&(" + LOGIN_ATTR_VALUE + '=' + user.getName() + ')' + FILTER_VALUE + ')', controls); if (users == null || !users.hasMore()) { //    AD if (!user.getFullName().startsWith(FIRED_STRING_VALUE)) { user.setFullName(FIRED_STRING_VALUE + ' ' + user.getFullName()); } } else { Preferences preferences = preferencesManager. getPreferences(user); String phone = preferences.getString( UserUtil.META_PROPERTY_PREFIX + "mobile"); if (phone == null || phone.isEmpty()) { //        try { Attribute attribute = ((SearchResult) users.next()) .getAttributes().get(PHONE_ATTR_VALUE); if (attribute != null) { phone = ((String) attribute.get()).replace("(", "").replace(")", ""); } if (phone != null) { preferences.setString( UserUtil.META_PROPERTY_PREFIX + "mobile", phone); } } catch (Exception exception) { exception.printStackTrace(System.err); } } } } } finally { if (context != null) { context.close(); } } } @Override public boolean allFieldsHidden() { return false; } @Override public String getName() { return "LDAP Importer"; } @Override public String getDescription() { return "      LDAP    ,    LDAP"; } @SuppressWarnings("rawtypes") @Override public String getDescription(Map params) { return "      LDAP    ,    LDAP"; } @Override public String[] getEnabledFieldKeys() { return new String[] { ADDRESS_NAME, LOGIN_NAME, PASSWORD_NAME, FILTER_NAME, BASE_NAME, LOGIN_ATTR_NAME, NAME_ATTR_NAME, MAIL_ATTR_NAME, PHONE_ATTR_NAME, DOMAIN_NAME, FIRED_STRING_NAME }; } @Override public String getFieldDefault(String key) throws ObjectConfigurationException { if (key.equals(ADDRESS_NAME)) { return ADDRESS_VALUE; } else if (key.equals(LOGIN_NAME)) { return LOGIN_VALUE; } else if (key.equals(PASSWORD_NAME)) { return PASSWORD_VALUE; } else if (key.equals(BASE_NAME)) { return BASE_VALUE; } else if (key.equals(NAME_ATTR_NAME)) { return NAME_ATTR_VALUE; } else if (key.equals(LOGIN_ATTR_NAME)) { return LOGIN_ATTR_VALUE; } else if (key.equals(MAIL_ATTR_NAME)) { return MAIL_ATTR_VALUE; } else if (key.equals(PHONE_ATTR_NAME)) { return PHONE_ATTR_VALUE; } else if (key.equals(DOMAIN_NAME)) { return DOMAIN_VALUE; } else if (key.equals(FILTER_NAME)) { return FILTER_VALUE; } else { return FIRED_STRING_VALUE; } } @Override public String getFieldDescription(String key) throws ObjectConfigurationException { if (key.equals(BASE_NAME)) { return "     DN"; } else if (key.equals(MAIL_ATTR_NAME)) { return "  ,   \" + @ +  \""; } else if (key.equals(FIRED_STRING_NAME)) { return "        LDAP"; } else if (key.equals(NAME_ATTR_NAME)) { return "  ,   "; } return ""; } @Override public String[] getFieldKeys() { return new String[] { ADDRESS_NAME, LOGIN_NAME, PASSWORD_NAME, FILTER_NAME, BASE_NAME, LOGIN_ATTR_NAME, NAME_ATTR_NAME, MAIL_ATTR_NAME, PHONE_ATTR_NAME, DOMAIN_NAME, FIRED_STRING_NAME }; } @Override public String getFieldName(String key) throws ObjectConfigurationException { if (key.equals(ADDRESS_NAME)) { return "  LDAP"; } else if (key.equals(LOGIN_NAME)) { return "  LDAP"; } else if (key.equals(PASSWORD_NAME)) { return "  LDAP"; } else if (key.equals(BASE_NAME)) { return " DN"; } else if (key.equals(NAME_ATTR_NAME)) { return "  "; } else if (key.equals(LOGIN_ATTR_NAME)) { return "  "; } else if (key.equals(MAIL_ATTR_NAME)) { return "  "; } else if (key.equals(PHONE_ATTR_NAME)) { return " "; } else if (key.equals(DOMAIN_NAME)) { return " "; } else if (key.equals(FILTER_NAME)) { return " "; } else { return ""; } } @Override public int getFieldType(String key) throws ObjectConfigurationException { return 0; } @SuppressWarnings("rawtypes") @Override public Map getFieldValues(String key) throws ObjectConfigurationException { return null; } @SuppressWarnings("rawtypes") @Override public void init(Map params) { } @Override public boolean isEnabled(String key) { return true; } @Override public boolean isI18NValues(String key) { return false; } } 

$ JIRA_HOME / atlassian-jira / WEB-INF / lib / рдореЗрдВ рдбрд╛рд▓реА рдЧрдИ рд╕реЗрд╡рд╛ рдХреЗ рд╕рд╛рде рд╕рдВрдХрд▓рд┐рдд рдЬрд╛рд░ рдлрд╝рд╛рдЗрд▓ (рдЬреАрд░рд╛ рдкреНрд▓рдЧрдЗрди SDK рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ)ред рдЖрдк рд╡реНрдпрд╡рд╕реНрдерд╛рдкрди тЖТ рд╕рд┐рд╕реНрдЯрдо тЖТ рд╕реЗрд╡рд╛ рдЕрдиреБрднрд╛рдЧ рдореЗрдВ рдПрдХ рд╕реЗрд╡рд╛ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред

рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдЬрд╛рдирдХрд╛рд░реА рдХрд┐рд╕реА рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧреАред

Source: https://habr.com/ru/post/In141144/


All Articles