Atlassian相关介绍参考博客:
https://www.us-forever.com/
Jira的分支版本
参考:
https://www.akeles.com/what-are-the-differences-between-jira-software-jira-service-desk-and-jira-core/
https://www.youtube.com/watch?v=TxbtOfyljoA
从Jira 7开始,Atlassian将Jira分成了三个独立的产品:
- Jira Core(商务)
- Jira Software(软件)
- Jira Service Desk(给IT用的)
后来发现虽然我用的是Jira 7.13.0来搭建的环境,但是如果使用Jira Service Desk的license的话,我依然会显示Jira Service Desk。
Jira的整体架构:
https://developer.atlassian.com/server/jira/platform/architecture-overview/
classes和URL的对应关系在这里声明了:
src/webapp/WEB-INF/classes/actions.xml
大概长这样:
<!-- Workflow Transitions -->
<action name="admin.workflow.ViewWorkflowTransition" alias="ViewWorkflowTransition" roles-required="admin">
<view name="success">/secure/admin/views/workflow/viewworkflowtransition.jsp</view>
<command name="moveWorkflowFunctionUp" alias="MoveWorkflowFunctionUp">
<view name="error">/secure/admin/views/workflow/viewworkflowtransition.jsp</view>
<view name="success">/secure/admin/views/workflow/viewworkflowtransition.jsp</view>
</command>
<command name="moveWorkflowFunctionDown" alias="MoveWorkflowFunctionDown">
<view name="error">/secure/admin/views/workflow/viewworkflowtransition.jsp</view>
<view name="success">/secure/admin/views/workflow/viewworkflowtransition.jsp</view>
</command>
</action>
每个action都有一个alias
属性,其实就是你在浏览器看到都URL的一部分。而name
属性就是这个alias对应的Java类。
原文讲得很清楚,看原文就可以了。
Jira插件
Jira的app其实就是一个插件(plugin或者叫做add-on)。
An app (also known as a plugin or add-on) is a bundle of code, resources and a special configuration file that can be installed on a Jira site to add new functionality, or change the behavior of existing features.
https://developer.atlassian.com/server/jira/platform/getting-started/
Jira有两种app:
- 系统apps:Jira自带的提供核心功能的app;
- 自定义第三方app:需要自行下载。
Jira APIs
REST APIs 和Java APIs。
Jira登录认证(Seraph)
Jira的登录认证是由Seraph来负责的。而Seraph 是由几个核心元素组成:
- Security Service
Security services用于确定特定的HTTP请求需要哪些角色限定。
Seraph有两个security services:the Path service and the WebWork service.
其中Path Service 用于对URL paths进行安全限定,可通过其自己的xm文件进行配置:seraph-paths.xml。
受限,在security-config.xml配置文件中需要有这样的配置:
<service class="com.atlassian.seraph.service.PathService">
<init-param>
<param-name>config.file</param-name>
<param-value>/seraph-paths.xml</param-value>
</init-param>
</service>
然后seraph-paths.xml中定义了特定url请求所需要的对应角色:
<seraph-paths>
<!-- You can configure any number of path elements -->
<path name="admin">
<url-pattern>/admin/*</url-pattern>
<role-name>myapp-administrators, myapp-owners</role-name>
</path>
</seraph-paths>
比如上面这个配置就定义了/admin/*
这样的url就必须myapp-administrators,myapp-owners这样角色的用户可以访问。
其中WebWork Service需要用actions.xml配置文件来进行配置:
<action name="project.AddProject" roles-required="admin">
<view name="input">/secure/admin/views/addproject.jsp</view>
</action>
比如上面这个就表示/secure/admin/views/addproject.jsp
这个url请求的需要admin角色才能操作。
- Interceptor
- Authenticator
Authenticator用于对用户进行认证(authenticate) , log them in, log them out 以及check their roles. - Controller
- Role Mapper
如何配置Seraph
可以在两个地方配置Seraph:
通过seraph-config.xml配置文件
Seraph的核心是通过seraph-config.xml来进行配置的。通常放在web应用的WEB-INF/classes
目录下。
<security-config>
<parameters>
<init-param>
<!--
the URL to redirect to when the user tries to access a protected resource (rather than clicking on
an explicit login link). Most of the time, this will be the same value as 'link.login.url'.
- if the URL is absolute (contains '://'), then redirect that URL (for SSO applications)
- else the context path will be prepended to this URL
If '${originalurl}' is present in the URL, it will be replaced with the context-relative URL that the user requested.
This gives SSO login pages the chance to redirect to the original page
-->
<param-name>login.url</param-name>
<param-value>/login.jsp?os_destination=${originalurl}</param-value>
<!-- <param-value>http://example.com/SSOLogin?target=${originalurl}</param-value>-->
</init-param>
<init-param>
<!--
the URL to redirect to when the user explicitly clicks on a login link (rather than being redirected after
trying to access a protected resource). Most of the time, this will be the same value as 'login.url'.
- same properties as login.url above
-->
<param-name>link.login.url</param-name>
<param-value>/secure/Dashboard.jspa?os_destination=${originalurl}</param-value>
<!-- <param-value>http://mycompany.com/SSOLogin?target=${originalurl}</param-value>-->
</init-param>
<init-param>
<!-- URL for logging out.
- If relative, Seraph just redirects to this URL, which is responsible for calling Authenticator.logout().
- If absolute (eg. SSO applications), Seraph calls Authenticator.logout() and redirects to the URL
-->
<param-name>logout.url</param-name>
<param-value>/secure/Logout!default.jspa</param-value>
<!-- <param-value>http://mycompany.com/SSOLogout</param-value>-->
</init-param>
<!-- The key that the original URL is stored with in the session -->
<init-param>
<param-name>original.url.key</param-name>
<param-value>os_security_originalurl</param-value>
</init-param>
<init-param>
<param-name>login.cookie.key</param-name>
<param-value>seraph.os.cookie</param-value>
</init-param>
<!-- Specify 3 characters to make cookie encoding unique for your application, to prevent collisions
if more than one Seraph-based app is used.
<init-param>
<param-name>cookie.encoding</param-name>
<param-value>xYz</param-value>
</init-param>
-->
<!-- Basic Authentication can be enabled by passing the authentication type as a configurable url parameter.
With this example, you will need to pass http://mycompany.com/anypage?os_authType=basic in the url to enable Basic Authentication -->
<init-param>
<param-name>authentication.type</param-name>
<param-value>os_authType</param-value>
</init-param>
</parameters>
<!-- Determines what roles (permissions) a user has. -->
<rolemapper class="com.atlassian.myapp.auth.MyRoleMapper"/>
<!-- A controller is not required. If not specified, security will always be on
<controller class="com.atlassian.myapp.setup.MyAppSecurityController" />
-->
<!-- Logs in users. Must be overridden for SSO apps -->
<authenticator class="com.atlassian.seraph.auth.DefaultAuthenticator"/>
<services>
<!-- Specifies role requirements for accessing specified URL paths -->
<service class="com.atlassian.seraph.service.PathService">
<init-param>
<param-name>config.file</param-name>
<param-value>/seraph-paths.xml</param-value>
</init-param>
</service>
<!-- Specifies role requirements to execute Webwork actions -->
<service class="com.atlassian.seraph.service.WebworkService">
<init-param>
<param-name>action.extension</param-name>
<param-value>jspa</param-value>
</init-param>
</service>
</services>
<interceptors>
<!-- <interceptor class="com.atlassian.myapp.SomeLoginInterceptor"/> -->
</interceptors>
</security-config>
通过过滤器(Filters)
与Seraph相关的,有两个Filter(com.atlassian.seraph.filter.LoginFilter
,com.atlassian.seraph.filter.SecurityFilter
),和一个Servlet(com.atlassian.seraph.logout.LogoutServlet
)是必需放在WEB-INF/web.xml
中的。
<filter>
<filter-name>login</filter-name>
<filter-class>com.atlassian.seraph.filter.LoginFilter</filter-class>
</filter>
<filter>
<filter-name>security</filter-name>
<filter-class>com.atlassian.seraph.filter.SecurityFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>login</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>security</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>logout</servlet-name>
<servlet-class>com.atlassian.seraph.logout.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>logout</servlet-name>
<url-pattern>/logout</url-pattern>
</servlet-mapping>
Jira的认证(authentication)方式
The Jira Server platform, Jira Software Server, and Jira Service Desk Server REST APIs有以下几种认证方式:
OAuth
使用Jira产生的Token来进行认证,虽然不太好实现,但是比较安全。
具体参考:https://developer.atlassian.com/server/jira/platform/oauth/
Basic authentication
其实就是在HTTP请求头中加上一个HTTP请求头,这种方式没那么安全,但是在脚本中或者命令行掉REST接口比较好用。
具体参考:https://developer.atlassian.com/server/jira/platform/basic-authentication/
比如CURL就可以这样用:
curl -u username:password -X GET -H "Content-Type: application/json" http://localhost:8080/rest/api/2/issue/createmeta
curl会自动帮你把提供的用户名密码计算加到Header中。
或者你也可以自己计算好之后,把它作为一个HTTP头来请求。
其实就是把username:password
进行base64编码,然后加到Authorization: Basic {base64}
即可。
对应到代码中是:
atlassian-jira-software-7.13.0-standalone/atlassian-jira/WEB-INF/lib/atlassian-seraph-3.0.3.jar!/com/atlassian/seraph/filter/HttpAuthFilter.class
继承自PasswordBasedLoginFilter
即先解码base64,然后传入username和password,返回一个UserPasswordPair对象。
new UserPasswordPair(creds.getUsername(), creds.getPassword(), false);
CAPTCHA
多次连续登陆失败之后,就会出现验证码。
Cookie-based authentication
就是用Cookie来进行认证。对应到代码中是:
atlassian-jira-software-7.13.0-standalone/atlassian-jira/WEB-INF/lib/atlassian-seraph-3.0.3.jar!/com/atlassian/seraph/filter/LoginFilter.class
继承自PasswordBasedLoginFilter
表单token的处理(防CSRF)
https://developer.atlassian.com/server/jira/platform/form-token-handling/
想要对某个Action进行 xsrf token验证,需要进行以下步骤:
1、首先定位到某个Action具体执行的方法,一般默认是doExecute()
2、在这个方法前加上注解:@com.atlassian.jira.security.xsrf.RequiresXsrfCheck
如果在自动化脚本中,可以使用以下HTTP头来绕过反CSRF校验机制:
X-Atlassian-Token: no-check
在Jira的java代码中生成token的方法为:
import com.atlassian.jira.security.xsrf.XsrfTokenGenerator;
XsrfTokenGenerator xsrfTokenGenerator = ComponentManager.getComponentInstanceOfType(XsrfTokenGenerator.class);
String token = xsrfTokenGenerator.generateToken(request);
Jira的WhiteList
在添加Gadget的地方输入了一个cqq.com(本地地址域名)和127.0.0.1都被认为是不合法的url,在log中返回了这个错误:
A request to http://127.0.0.1/gad/get.xml has been denied. To allow requests to this URL add the application URL to your whitelist (http://confluence.atlassian.com/x/KQfCDQ
查阅jira的官方文档,找到:
JIRA administrators can choose to allow incoming and outgoing connections and content from specified sources by adding URLs to the whitelist.
JIRA will display an error if content has been added that is not from an allowed source, and prompt the user to add the URL to the whitelist.
而配置jira白名单需要JIRA Administrators权限。
参考:
https://confluence.atlassian.com/display/GADGETS/Whitelisting+External+Gadgets
https://confluence.atlassian.com/adminjiraserver073/configuring-the-whitelist-861254007.html
IDEA trick
有一些jar包在META-INF目录下,只能手动解压才能加入library中(否则无法进入调试)。
杂
atlassian-jira/WEB-INF/classes/com/atlassian/jira/web/filters/accesslog/AccessLogFilter
用于写入log。
由于安装jira的过程需要将这些文件解压,所以会有较高的磁盘io消耗。
$JIRA_INSTALL/atlassian-jira/WEB-INF/classes/atlassian-bundled-plugins.zip is extracted to $JIRA_HOME/plugins/.bundled-plugins.
$JIRA_HOME/plugins/installed-plugins is extracted to $JIRA_HOME/plugins/.osgi-plugins.
若碰到错误,缓解方法是:增加插件timeout的时间间隔:
-Datlassian.plugins.enable.wait=300
参考:https://confluence.atlassian.com/jirakb/jira-applications-system-plugin-timeout-while-waiting-for-add-ons-to-enable-212173447.html?
附录
Practical JIRA administration(Jira管理实用手册)
http://117.3.71.125:8080/dspace/bitstream/DHKTDN/6977/1/6265.Practical%20JIRA%20administration.pdf
不过这个主要是将管理员角色上的,不是jira的产品介绍。