OAuth 单点登录

  • 文档创建者:susie
  • 编辑次数:19次
  • 最近更新:Roxy 于 2020-05-11
  • 1. 概述

    1.1 版本

    报表服务器版本
    10.0

    1.2 问题描述

    使用 OAuth 服务器作为统一登录,集成 FineReport 系统,需要实现登录了 OAuth 后就可以直接访问平台, 不再需要平台登录。

    1.3 解决思路

    以 OAuth 授权码模式为例,流程如下:

    1.3.1 获取 code

    1)OAuth 服务器端注册了单点客户端的信息,包括 client_id, client_secret, redirect_uri(可选), logout_uri(可选)

    2)问 OAuth 认证地址请求(简称 oauthAuthorizeUrl ),得到一个 code 。

    请求参数( queryString 型参数):

    参数名解释
    client_id注册的客户端 ID
    redirect_uri回调地址
    response_type固定值 code

    最后重定向到 redirect_uri,并带上参数 code 。

    1.3.2 获取 access_token

    1)带上参数 code 访问 OAuth 获取accessToken的请求(简称 oauthTokenUrl ),获取 access_token 。

    请求类型:POST

    请求参数( queryString 型参数):

    参数名解释
    client_id注册的客户端 ID
    redirect_uri回调地址
    grant_typeauthorization_code
    client_secret可选
    code上步骤的 code

    返回值:{access_token: ""}

    2)(可选)access_token可能有效期较短,可以使用刷新 token 接口进行刷新。

    1.3.3 获取登录用户信息

    1)使用 access_token 获取登录的用户信息

    请求类型:GET

    请求参数(queryString 型参数):

    参数名解释
    client_id注册的客户端 ID
    access_token

    1.3.4 登录

    根据此用户名去调用平台的后台登录方法进行登录。

    2. 示例

    2.1 操作步骤

    2.1.1 文件准备

    点击下载所需文件:OAuth.zip

    2.1.2 放置 class 文件

    将编译好的两个 class 文件:FrOauthFilter 和 FrOauthFilter$OauthLoginInfo 置于%FR_HOME%/webapps/webroot/WEB_INF/classes/com/fr目录下,如下图所示:

    16.png

    FrOauthFilter 文件源码如下所示:

    package com.fr;

    import com.fr.base.TemplateUtils;
    import com.fr.data.NetworkHelper;
    import com.fr.decision.mobile.terminal.TerminalHandler;
    import com.fr.decision.webservice.utils.DecisionServiceConstants;
    import com.fr.decision.webservice.v10.login.LoginService;
    import com.fr.decision.webservice.v10.login.TokenResource;
    import com.fr.general.http.HttpToolbox;
    import com.fr.json.JSONObject;
    import com.fr.log.FineLoggerFactory;
    import com.fr.stable.StringUtils;
    import com.fr.stable.web.Device;
    import com.fr.store.StateHubManager;
    import com.fr.store.StateHubService;
    import com.fr.third.springframework.web.util.WebUtils;

    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.Serializable;
    import java.util.ArrayList;
    import java.util.List;

    /**
     * @Author: Elijah
     * @Create: 2019-07-10
     * @Desciption:
     */
    public class FrOauthFilter implements Filter {

        private static final StateHubService OAUTH_SERVICE = StateHubManager.applyForService("oauth");
        private static final String COOKIE_AUTH = "oauth_access_token";
        private static final int TIME = 3600000 * 24;

        private String oauthTokenUrl;     /** oauth获取accessToken地址,无需包括请求参数*/
        private String oauthUserInfoUrl;  /** oauth获取用户信息地址*/
        private String oauthUserName = "username"; /**oauth获取用户信息接口返回值中的用户名字段*/
        private String redirectUrl;      /** 需要重定向回来的地址,一般就是工程地址*/
        private String oauthClientId;    /** oauth注册的客户端id*/
        private String oauthClientSecret; /** oauth注册的客户端秘钥*/
        private String oauthAuthorizeUrl;  /** oauth认证地址,无需包括请求参数*/
        private List<String> oauthExcludeUrl = new ArrayList<String>();

        private String decisionRoot;

        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            this.oauthTokenUrl= filterConfig.getInitParameter("oauthTokenUrl");
            this.oauthUserInfoUrl = filterConfig.getInitParameter("oauthUserInfoUrl");
            this.redirectUrl = filterConfig.getInitParameter("redirectUrl");
            this.oauthClientId = filterConfig.getInitParameter("oauthClientId");
            this.oauthClientSecret = filterConfig.getInitParameter("oauthClientSecret");
            this.oauthAuthorizeUrl = filterConfig.getInitParameter("oauthAuthorizeUrl");


            this.oauthUserName = filterConfig.getInitParameter("oauthUserName") != null ? filterConfig.getInitParameter("oauthUserName") : oauthUserName;
            String excludeUrls = filterConfig.getInitParameter("oauthExcludeUrl");
            String[] array = excludeUrls.split(",");
            for (String s: array) {
                oauthExcludeUrl.add(filterConfig.getServletContext().getContextPath() + s.trim());
            }

            try {
                this.decisionRoot = TemplateUtils.render(DecisionServiceConstants.MAIN_PAGE_URL);
            } catch (Exception e) {
                FineLoggerFactory.getLogger().error(e, e.getMessage());
            }
        }

        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            OauthLoginInfo loginInfo = getCurrentUser(request);

            if (excludeUrl(request)) {
                filterChain.doFilter(request, response);
                return;
            }

            if (loginInfo != null ) {
                /**如果oauth已经登录, 即已经存在本地会话,则刷新平台token*/

                refreshDecisionToken(request, response, loginInfo);
                filterChain.doFilter(request, response);
            } else {
                /**如果oauth没有登录,则判断是否携带oauth的code*/
                String code = getCode(request);
                if ( code != null) {
                    doOauth(request, response, filterChain, code);
                }else {
                    /**直接重定向到oauth认证地址*/
                    response.sendRedirect(oauthAuthorizeUrl + "?client_id=" + oauthClientId + "&response_type=code" + "&redirect_uri=" + redirectUrl);
                }
            }
        }

        @Override
        public void destroy() {

        }

        private void storeLoginUser(HttpServletRequest request, HttpServletResponse response, String userName, String accessToken) {
            try {
                String decisionToken = LoginService.getInstance().login(request, response, userName);
                request.setAttribute("fine_auth_token", decisionToken);
                Cookie cookie = new Cookie(COOKIE_AUTH, accessToken);
                cookie.setPath("/");
                cookie.setHttpOnly(true);
                response.addCookie(cookie);
                OAUTH_SERVICE.put(accessToken, new OauthLoginInfo(userName, accessToken, decisionToken), TIME);
            } catch (Exception e) {
                FineLoggerFactory.getLogger().error(e, e.getMessage());
            }
        }

        private void refreshDecisionToken(HttpServletRequest request, HttpServletResponse response, OauthLoginInfo loginInfo) {
            try {
                String oldToken = TokenResource.COOKIE.getToken(request);
                Device device = NetworkHelper.getDevice(request);
                LoginService.getInstance().loginStatusValid(oldToken, TerminalHandler.getTerminal(request, device));
            } catch (Exception e) {
                try {
                    String decisionToken = LoginService.getInstance().login(request, response, loginInfo.userName);
                    request.setAttribute("fine_auth_token", decisionToken);
                    OAUTH_SERVICE.put(loginInfo.accessToken, new OauthLoginInfo(loginInfo.userName, loginInfo.accessToken, decisionToken), TIME);
                } catch (Exception ex) {
                    FineLoggerFactory.getLogger().error(e.getMessage(), e);
                }
            }
        }

        private static OauthLoginInfo getCurrentUser(HttpServletRequest request) {
            Cookie cookie = WebUtils.getCookie(request, COOKIE_AUTH);
            if (cookie == null) {
                return null;
            }
            try {
                return OAUTH_SERVICE.get(cookie.getValue());
            } catch (Exception e) {
                return null;
            }
        }

        private boolean isLoginPage(HttpServletRequest request) {
            if (request.getRequestURI().endsWith("/login")) {
                return true;
            }
            String refer = request.getHeader("refer");
            return refer != null && refer.contains(decisionRoot + "/login");
        }

        private void doOauth(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain, String code) throws IOException, ServletException {
            String accessToken = null;
            try {
                /** (1) 获取access_token*/
                JSONObject result = new JSONObject(HttpToolbox.post(oauthTokenUrl + "?client_id=" + oauthClientId + "&client_secret=" + oauthClientSecret + "&grant_type=authorization_code" + "&code=" + code + "&redirect_uri=" + redirectUrl, null));
                accessToken = result.getString("access_token");
            } catch (IOException e) {
                FineLoggerFactory.getLogger().error(e.getMessage(), e);
                response.sendRedirect(oauthAuthorizeUrl + "?client_id=" + oauthClientId + "&response_type=code" + "&redirect_uri=" + redirectUrl);
            }
            if (StringUtils.isNotEmpty(accessToken)) {
                /** (2) 再根据accessToken去请求oauthUserInfoUrl得到用户名*/
                JSONObject userInfo = new JSONObject(HttpToolbox.get(oauthUserInfoUrl + "?client_id=" + oauthClientId + "&access_token=" + accessToken, null));
                String userName = userInfo.getString(oauthUserName);
                /** (3) 建立本地会话*/
                storeLoginUser(request, response, userName, accessToken);
                filterChain.doFilter(request, response);
            }else {
                /** 如果获取不到, 说明code失效则重定向到oauth认证地址*/
                FineLoggerFactory.getLogger().error("oauth code is invalid");
                response.sendRedirect(oauthAuthorizeUrl + "?client_id=" + oauthClientId + "&response_type=code" + "&redirect_uri=" + redirectUrl);
            }
        }

        private boolean excludeUrl(HttpServletRequest request) {
            String url = request.getRequestURI();
            for (String exclude: oauthExcludeUrl) {
                if (exclude.equals(url) || (exclude.endsWith("/*") && url.startsWith(exclude.substring(0, exclude.indexOf("/*"))))) {
                    return true;
                }
            }
            return false;
        }

        public static void deleteTicket(HttpServletRequest request, HttpServletResponse response){
            OauthLoginInfo loginInfo = getCurrentUser(request);
            if (loginInfo != null) {
                try {
                    OAUTH_SERVICE.delete(loginInfo.accessToken);
                } catch (Exception e) {
                    FineLoggerFactory.getLogger().error(e.getMessage(), e);
                }
                Cookie cookie = new Cookie(COOKIE_AUTH, "");
                cookie.setPath("/");
                cookie.setMaxAge(0);
                response.addCookie(cookie);
            }
        }

        private String getCode(HttpServletRequest request) {
            return request.getParameter("code");
        }



        public class OauthLoginInfo implements Serializable {
            private static final long serialVersionUID = -5100721982500534486L;
            String userName;
            String accessToken;
            String decisionToken;
            String code;
            boolean decisionLogout;

            public OauthLoginInfo() {
            }

            public OauthLoginInfo(String userName, String accessToken, String decisionToken) {
                this.userName = userName;
                this.accessToken = accessToken;
                this.decisionToken = decisionToken;
            }

            public String getUserName() {
                return userName;
            }

            public void setUserName(String userName) {
                this.userName = userName;
            }

            public String getAccessToken() {
                return accessToken;
            }

            public void setAccessToken(String accessToken) {
                this.accessToken = accessToken;
            }

            public String getDecisionToken() {
                return decisionToken;
            }

            public void setDecisionToken(String decisionToken) {
                this.decisionToken = decisionToken;
            }

            public String getCode() {
                return code;
            }

            public void setCode(String code) {
                this.code = code;
            }

            public boolean isDecisionLogout() {
                return decisionLogout;
            }

            public void setDecisionLogout(boolean decisionLogout) {
                this.decisionLogout = decisionLogout;
            }

            public OauthLoginInfo decisionLogout(boolean decisionLogout) {
                this.decisionLogout = decisionLogout;
                return this;
            }
        }
    }

    FrOauthFilter$OauthLoginInfo 文件源码如下所示:

    package com.fr;
     
    import com.fr.base.TemplateUtils;
    import com.fr.data.NetworkHelper;
    import com.fr.decision.mobile.terminal.TerminalHandler;
    import com.fr.decision.webservice.utils.DecisionServiceConstants;
    import com.fr.decision.webservice.v10.login.LoginService;
    import com.fr.decision.webservice.v10.login.TokenResource;
    import com.fr.general.http.HttpToolbox;
    import com.fr.json.JSONObject;
    import com.fr.log.FineLoggerFactory;
    import com.fr.stable.StringUtils;
    import com.fr.stable.web.Device;
    import com.fr.store.StateHubManager;
    import com.fr.store.StateHubService;
    import com.fr.third.springframework.web.util.WebUtils;
     
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.Serializable;
    import java.util.ArrayList;
    import java.util.List;
     
    /**
     * @Author: Elijah
     * @Create: 2019-07-10
     * @Desciption:
     */
    public class FrOauthFilter implements Filter {
     
        private static final StateHubService OAUTH_SERVICE = StateHubManager.applyForService("oauth");
        private static final String COOKIE_AUTH = "oauth_access_token";
        private static final int TIME = 3600000 * 24;
     
        private String oauthTokenUrl;     //oauth获取accessToken地址,无需包括请求参数
        private String oauthUserInfoUrl;  //oauth获取用户信息地址
        private String oauthUserName = "username"; //oauth获取用户信息接口返回值中的用户名字段
        private String redirectUrl;      //需要重定向回来的地址,一般就是工程地址
        private String oauthClientId;    //oauth注册的客户端id
        private String oauthClientSecret; //oauth注册的客户端秘钥
        private String oauthAuthorizeUrl;  //oauth认证地址,无需包括请求参数
        private String oauthLogoutUrl;//oauth登出地址,无需包括请求参数
        private List<String> oauthExcludeUrl = new ArrayList<String>();
     
        private String decisionRoot;
     
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            this.oauthTokenUrl= filterConfig.getInitParameter("oauthTokenUrl");
            this.oauthUserInfoUrl = filterConfig.getInitParameter("oauthUserInfoUrl");
            this.redirectUrl = filterConfig.getInitParameter("redirectUrl");
            this.oauthClientId = filterConfig.getInitParameter("oauthClientId");
            this.oauthClientSecret = filterConfig.getInitParameter("oauthClientSecret");
            this.oauthAuthorizeUrl = filterConfig.getInitParameter("oauthAuthorizeUrl");
            this.oauthLogoutUrl = filterConfig.getInitParameter("oauthLogoutUrl");
     
     
            this.oauthUserName = filterConfig.getInitParameter("oauthUserName") != null ? filterConfig.getInitParameter("oauthUserName") : oauthUserName;
            String excludeUrls = filterConfig.getInitParameter("oauthExcludeUrl");
            String[] array = excludeUrls.split(",");
            for (String s: array) {
                oauthExcludeUrl.add(filterConfig.getServletContext().getContextPath() + s.trim());
            }
     
            try {
                this.decisionRoot = TemplateUtils.render(DecisionServiceConstants.MAIN_PAGE_URL);
            } catch (Exception e) {
                FineLoggerFactory.getLogger().error(e, e.getMessage());
            }
        }
     
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            OauthLoginInfo loginInfo = getCurrentUser(request);
     
            if (excludeUrl(request)) {
                filterChain.doFilter(request, response);
                return;
            }
     
            if (loginInfo != null ) {
                //如果oauth已经登录, 即已经存在本地会话,则刷新平台token
     
                refreshDecisionToken(request, response, loginInfo);
                filterChain.doFilter(request, response);
            } else {
                //如果oauth没有登录,则判断是否携带oauth的code
                String code = getCode(request);
                if ( code != null) {
                    doOauth(request, response, filterChain, code);
                }else {
                    //直接重定向到oauth认证地址
                    response.sendRedirect(oauthAuthorizeUrl + "?client_id=" + oauthClientId + "&response_type=code" + "&redirect_uri=" + redirectUrl);
                }
            }
        }
     
        @Override
        public void destroy() {
     
        }
     
        private void storeLoginUser(HttpServletRequest request, HttpServletResponse response, String userName, String accessToken) {
            try {
                String decisionToken = LoginService.getInstance().login(request, response, userName);
                request.setAttribute("fine_auth_token", decisionToken);
                Cookie cookie = new Cookie(COOKIE_AUTH, accessToken);
                cookie.setPath("/");
                cookie.setHttpOnly(true);
                response.addCookie(cookie);
                OAUTH_SERVICE.put(accessToken, new OauthLoginInfo(userName, accessToken, decisionToken), TIME);
            } catch (Exception e) {
                FineLoggerFactory.getLogger().error(e, e.getMessage());
            }
        }
     
        private void refreshDecisionToken(HttpServletRequest request, HttpServletResponse response, OauthLoginInfo loginInfo) {
            try {
                String oldToken = TokenResource.COOKIE.getToken(request);
                Device device = NetworkHelper.getDevice(request);
                LoginService.getInstance().loginStatusValid(oldToken, TerminalHandler.getTerminal(request, device));
            } catch (Exception e) {
                try {
                    String decisionToken = LoginService.getInstance().login(request, response, loginInfo.userName);
                    request.setAttribute("fine_auth_token", decisionToken);
                    OAUTH_SERVICE.put(loginInfo.accessToken, new OauthLoginInfo(loginInfo.userName, loginInfo.accessToken, decisionToken), TIME);
                } catch (Exception ex) {
                    FineLoggerFactory.getLogger().error(e.getMessage(), e);
                }
            }
        }
     
        private static OauthLoginInfo getCurrentUser(HttpServletRequest request) {
            Cookie cookie = WebUtils.getCookie(request, COOKIE_AUTH);
            if (cookie == null) {
                return null;
            }
            try {
                return OAUTH_SERVICE.get(cookie.getValue());
            } catch (Exception e) {
                return null;
            }
        }
     
        private boolean isLoginPage(HttpServletRequest request) {
            if (request.getRequestURI().endsWith("/login")) {
                return true;
            }
            String refer = request.getHeader("refer");
            return refer != null && refer.contains(decisionRoot + "/login");
        }
     
        private void doOauth(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain, String code) throws IOException, ServletException {
            String accessToken = null;
            try {
                // (1) 获取access_token
                JSONObject result = new JSONObject(HttpToolbox.post(oauthTokenUrl + "?client_id=" + oauthClientId + "&client_secret=" + oauthClientSecret + "&grant_type=authorization_code" + "&code=" + code + "&redirect_uri=" + redirectUrl, null));
                accessToken = result.getString("access_token");
            } catch (IOException e) {
                FineLoggerFactory.getLogger().error(e.getMessage(), e);
                response.sendRedirect(oauthAuthorizeUrl + "?client_id=" + oauthClientId + "&response_type=code" + "&redirect_uri=" + redirectUrl);
            }
            if (StringUtils.isNotEmpty(accessToken)) {
                // (2) 再根据accessToken去请求oauthUserInfoUrl得到用户名
                JSONObject userInfo = new JSONObject(HttpToolbox.get(oauthUserInfoUrl + "?client_id=" + oauthClientId + "&access_token=" + accessToken, null));
                String userName = userInfo.getString(oauthUserName);
                // (3) 建立本地会话
                storeLoginUser(request, response, userName, accessToken);
                filterChain.doFilter(request, response);
            }else {
                // 如果获取不到, 说明code失效则重定向到oauth认证地址
                FineLoggerFactory.getLogger().error("oauth code is invalid");
                response.sendRedirect(oauthAuthorizeUrl + "?client_id=" + oauthClientId + "&response_type=code" + "&redirect_uri=" + redirectUrl);
            }
        }
     
        private boolean excludeUrl(HttpServletRequest request) {
            String url = request.getRequestURI();
            for (String exclude: oauthExcludeUrl) {
                if (exclude.equals(url) || (exclude.endsWith("/*") && url.startsWith(exclude.substring(0, exclude.indexOf("/*"))))) {
                    return true;
                }
            }
            return false;
        }
     
        public static void deleteTicket(HttpServletRequest request, HttpServletResponse response){
            OauthLoginInfo loginInfo = getCurrentUser(request);
            if (loginInfo != null) {
                try {
                    OAUTH_SERVICE.delete(loginInfo.accessToken);
                } catch (Exception e) {
                    FineLoggerFactory.getLogger().error(e.getMessage(), e);
                }
                Cookie cookie = new Cookie(COOKIE_AUTH, "");
                cookie.setPath("/");
                cookie.setMaxAge(0);
                response.addCookie(cookie);
            }
        }
     
        private String getCode(HttpServletRequest request) {
            return request.getParameter("code");
        }
     
     
     
        public class OauthLoginInfo implements Serializable {
            private static final long serialVersionUID = -5100721982500534486L;
            String userName;
            String accessToken;
            String decisionToken;
            String code;
            boolean decisionLogout;
     
            public OauthLoginInfo() {
            }
     
            public OauthLoginInfo(String userName, String accessToken, String decisionToken) {
                this.userName = userName;
                this.accessToken = accessToken;
                this.decisionToken = decisionToken;
            }
     
            public String getUserName() {
                return userName;
            }
     
            public void setUserName(String userName) {
                this.userName = userName;
            }
     
            public String getAccessToken() {
                return accessToken;
            }
     
            public void setAccessToken(String accessToken) {
                this.accessToken = accessToken;
            }
     
            public String getDecisionToken() {
                return decisionToken;
            }
     
            public void setDecisionToken(String decisionToken) {
                this.decisionToken = decisionToken;
            }
     
            public String getCode() {
                return code;
            }
     
            public void setCode(String code) {
                this.code = code;
            }
     
            public boolean isDecisionLogout() {
                return decisionLogout;
            }
     
            public void setDecisionLogout(boolean decisionLogout) {
                this.decisionLogout = decisionLogout;
            }
     
            public OauthLoginInfo decisionLogout(boolean decisionLogout) {
                this.decisionLogout = decisionLogout;
                return this;
            }
        }
    }

    2.1.3 新建 web.xml

    根据注释配置 OAuth 登出地址认证地址、 获取 token 地址重定向回来地址注册的 client_id注册的 client_secret 、获取用户信息接口地址获取用户信息接口返回值中的平台用户名字段等 web.xml 中的参数,然后将其放在%FR_HOME%/webapps/webroot/WEB_INF目录下,web.xml 文件代码如下所示:

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app
            xmlns="http://java.sun.com/xml/ns/j2ee"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
            version="2.4">
        <display-name>Template WebApp</display-name>
        <mime-mapping>
            <extension>msi</extension>
            <mime-type>application/x-msi</mime-type>
        </mime-mapping>


        <!--设置oauth登出地址,非必须-->
        <context-param>
            <param-name>oauthLogoutUrl</param-name>
            <param-value>https://www.example.com/oauth/authorize/logout</param-value>
        </context-param>
        <filter>
            <filter-name>FrOauthFilter</filter-name>
            <filter-class>com.fr.FrOauthFilter</filter-class>

            <init-param>
                <!--oauth认证地址-->
                <param-name>oauthAuthorizeUrl</param-name>
                <param-value>https://www.example.com/oauth/authorize</param-value>
            </init-param>

            <init-param>
                <!--oauth获取token地址-->
                <param-name>oauthTokenUrl</param-name>
                <param-value>https://www.example.com/oauth/token</param-value>
            </init-param>

            <init-param>
                <!--从oauth重定向回来地址,一般就是fr工程地址, 集群下则为nginx转发地址-->
                <param-name>redirectUrl</param-name>
                <param-value>http://www.aaa.com/webroot/decision</param-value>
            </init-param>

            <init-param>
                <!--在oauth注册的client_id-->
                <param-name>oauthClientId</param-name>
                <param-value>xxxxx</param-value>
            </init-param>

            <init-param>
                <!--在oauth注册的client_secret,非必须,没有就删除-->
                <param-name>oauthClientSecret</param-name>
                <param-value></param-value>
            </init-param>

            <init-param>
                <!--oauth获取用户信息接口地址-->
                <param-name>oauthUserInfoUrl</param-name>
                <param-value>https://www.example.com/oauth/userinfo</param-value>
            </init-param>


            <init-param>
                <!--oauth获取用户信息接口返回值中的平台用户名字段-->
                <param-name>oauthUserName</param-name>
                <param-value>username</param-value>
            </init-param>

            <!--排除远程设计和其他 -->
            <init-param>
                <param-name>oauthExcludeUrl</param-name>
                <param-value>/decision/remote/design/*</param-value>
            </init-param>

        </filter>
        <filter-mapping>
            <filter-name>FrOauthFilter</filter-name>
            <url-pattern>/decision/*</url-pattern>
        </filter-mapping>
    </web-app>

     注:其中 oauthUserName 参数有些特别,标记了用户信息接口的返回值中,哪个字段对应平台用户名,比如 oauthUserInfoUrl 接口返回了{ username: "张三", phone: "xxx", email:"ssss"}这样 JSON 接口的数据,则填写 username 。

    2.1.4 单点登出

    如果需要退出平台后,也同时退出 OAuth 系统,还需要进行下列配置。

    1)web.xml 中配置登出地址,如下图所示:

    9.png

    2)添加 logout.jsp ,将 loggout.jsp 文件放到%FR_HOME%/webapps/webroot目录下,代码如下所示:

    <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
    <%@ page import="com.fr.FrOauthFilter" %>
    <html>
    <body>
    <%
        FrOauthFilter.deleteTicket(request, response);
        response.sendRedirect(application.getInitParameter("oauthLogoutUrl"));
    %>
    </body>
    </html>

    3)配置平台登录页

    管理系统>外观配置>登录页处选择设置登录网页,设置网页 URL 为第 2 步中放置的 jsp 地址,点击保存,如下图所示:

    1586416154872498.png 

    2.2 效果查看

    重启工程后进行登录,如下图所示:

    1.gif

    3. 注意事项

    1)由于 OAuth 规范不严格,此仅作为 OAuth 登录的示例 ,可能需要根据客户的 OAuth 服务器要求修改,主要集中在 doOauth 方法中修改相关内容。

    2)本例中用户信息接口返回值为 JSON 格式数据,比如为{username : "aaa", id: "123"},此时 web.xml 中的须配置成如下图所示:

    1573721793630415.png

    如果返回值为{ user: {username : "aaa", id: "aaa"}},那么 param-value 则应为 user.username 。

    3)若 OAuth 系统使用了 https,则需要导入证书到报表服务器的 JAVA 环境中,否则会报错。

    附件列表


    主题: 部署集成
    • 有帮助
    • 没帮助
    • 只是浏览
    • 评价文档,奖励 1 ~ 100 随机 F 豆!