java微服务 Spring Security+oauth2 对form提交 鉴权

文章讲述了在微服务系统中使用OAuth2的Bearer方式进行鉴权时遇到的问题,即form提交导致无法正常鉴权。解决方案包括修改ueditor源码,增加额外参数传递access_token,并在后台过滤器和请求头处理中适应这种形式的提交。
摘要由CSDN通过智能技术生成

场景:微服务系统中使用oauth2 的 Bearer 方式鉴权,对于from提交的数据,无法鉴权,百度的富文本编辑器 ueditor 中上传图片都是使用form 伪ajax提交,导致401

因为from提交无法设置header

解决方式:

1、修改百度富文本编辑器的源码ueditor.all.min.js,在调用上传图片方法的时候,加入额外参数

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

/**

         * 获取服务器提交的额外参数列表

         * @command serverparam

         * @method queryCommandValue

         * @param { String } cmd 命令字符串

         * @example

         * ```javascript

         * editor.queryCommandValue( 'serverparam' ); //返回对象 {'key': 'value'}

         * ```

         */

        'serverparam': {

          execCommand: function (cmd, key, value) {

            if (key === undefined || key === null) { //不传参数,清空列表

              serverParam = {};

            else if (utils.isString(key)) { //传入键值

              if (value === undefined || value === null) {

                delete serverParam[key];

              else {

                serverParam[key] = value;

              }

            else if (utils.isObject(key)) { //传入对象,覆盖列表项

              utils.extend(serverParam, key, true);

            else if (utils.isFunction(key)) { //传入函数,添加列表项

              utils.extend(serverParam, key(), true);

            }

          },

          queryCommandValue: function () {

            if(!serverParam){

              serverParam={};

            }        //修改的地方

            var accessToken=JSON.parse(window.sessionStorage.getItem("pigx-access_token")).content;

            var token = accessToken || '';

            serverParam['_authorization']= token;

            serverParam['_domain']= window.location.host;

            console.log(serverParam)

            return serverParam || {};

          }

        }

 2、还有修改doAjax方法

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

function doAjax(url, ajaxOptions) {

      var xhr = creatAjaxRequest(),

        //是否超时

        timeIsOut = false,

        //默认参数

        defaultAjaxOptions = {

          method: "POST",

          timeout: 5000,

          async: true,

          data: {},//需要传递对象的话只能覆盖

          onsuccess: function () {

          },

          onerror: function () {

          }

        };

      if (typeof url === "object") {

        ajaxOptions = url;

        url = ajaxOptions.url;

      }

      if (!xhr || !url) return;

      var ajaxOpts = ajaxOptions ? utils.extend(defaultAjaxOptions, ajaxOptions) : defaultAjaxOptions;

      var submitStr = json2str(ajaxOpts);  // { name:"Jim",city:"Beijing" } --> "name=Jim&city=Beijing"

      //如果用户直接通过data参数传递json对象过来,则也要将此json对象转化为字符串

      if (!utils.isEmptyObject(ajaxOpts.data)) {

        submitStr += (submitStr ? "&" "") + json2str(ajaxOpts.data);

      }

      //超时检测

      var timerID = setTimeout(function () {

        if (xhr.readyState != 4) {

          timeIsOut = true;

          xhr.abort();

          clearTimeout(timerID);

        }

      }, ajaxOpts.timeout);

      var method = ajaxOpts.method.toUpperCase();

      var str = url + (url.indexOf("?") == -1 ? "?" "&") + (method == "POST" "" : submitStr + "&noCache=" + +new Date);

      xhr.open(method, str, ajaxOpts.async);

      xhr.onreadystatechange = function () {

        if (xhr.readyState == 4) {

          if (!timeIsOut && xhr.status == 200) {

            ajaxOpts.onsuccess(xhr);

          else {

            ajaxOpts.onerror(xhr);

          }

        }

      };    //修改的地方

      var accessToken=JSON.parse(window.sessionStorage.getItem("pigx-access_token")).content;

      var token = accessToken || '';

      xhr.setRequestHeader('Authorization''Bearer '+token);

      xhr.setRequestHeader('X-DOMAIN', window.location.host);

      if (method == "POST") {

        xhr.setRequestHeader('Content-Type''application/x-www-form-urlencoded');

        xhr.send(submitStr);

      else {

        xhr.send(null);

      }

    }

 3、修改复制的图片自动上传的方法

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

/**

   * @description

   * 1.拖放文件到编辑区域,自动上传并插入到选区

   * 2.插入粘贴板的图片,自动上传并插入到选区

   * @author Jinqn

   * @date 2013-10-14

   */

  UE.plugin.register('autoupload'function () {

    function sendAndInsertFile(file, editor) {

      var me = editor;

      //模拟数据

      var fieldName, urlPrefix, maxSize, allowFiles, actionUrl,

        loadingHtml, errorHandler, successHandler,

        filetype = /image\/\w+/i.test(file.type) ? 'image' 'file',

        loadingId = 'loading_' + (+new Date()).toString(36);

      fieldName = me.getOpt(filetype + 'FieldName');

      urlPrefix = me.getOpt(filetype + 'UrlPrefix');

      maxSize = me.getOpt(filetype + 'MaxSize');

      allowFiles = me.getOpt(filetype + 'AllowFiles');

      actionUrl = me.getActionUrl(me.getOpt(filetype + 'ActionName'));

      errorHandler = function (title) {

        var loader = me.document.getElementById(loadingId);

        loader && domUtils.remove(loader);

        me.fireEvent('showmessage', {

          'id': loadingId,

          'content': title,

          'type''error',

          'timeout': 4000

        });

      };

      if (filetype == 'image') {

        loadingHtml = '<img class="loadingclass" id="' + loadingId + '" src="' +

          me.options.themePath + me.options.theme +

          '/images/spacer.gif" title="' + (me.getLang('autoupload.loading') || '') + '" >';

        successHandler = function (data) {

          var link = urlPrefix + data.url,

            loader = me.document.getElementById(loadingId);

          if (loader) {

            loader.setAttribute('src', link);

            loader.setAttribute('_src', link);

            loader.setAttribute('title', data.title || '');

            loader.setAttribute('alt', data.original || '');

            loader.removeAttribute('id');

            domUtils.removeClasses(loader, 'loadingclass');

          }

        };

      else {

        loadingHtml = '<p>' +

          '<img class="loadingclass" id="' + loadingId + '" src="' +

          me.options.themePath + me.options.theme +

          '/images/spacer.gif" title="' + (me.getLang('autoupload.loading') || '') + '" >' +

          '</p>';

        successHandler = function (data) {

          var link = urlPrefix + data.url,

            loader = me.document.getElementById(loadingId);

          var rng = me.selection.getRange(),

            bk = rng.createBookmark();

          rng.selectNode(loader).select();

          me.execCommand('insertfile', {'url': link});

          rng.moveToBookmark(bk).select();

        };

      }

      /* 插入loading的占位符 */

      me.execCommand('inserthtml', loadingHtml);

      /* 判断后端配置是否没有加载成功 */

      if (!me.getOpt(filetype + 'ActionName')) {

        errorHandler(me.getLang('autoupload.errorLoadConfig'));

        return;

      }

      /* 判断文件大小是否超出限制 */

      if (file.size > maxSize) {

        errorHandler(me.getLang('autoupload.exceedSizeError'));

        return;

      }

      /* 判断文件格式是否超出允许 */

      var fileext = file.name ? file.name.substr(file.name.lastIndexOf('.')) : '';

      if ((fileext && filetype != 'image') || (allowFiles && (allowFiles.join('') + '.').indexOf(fileext.toLowerCase() + '.') == -1)) {

        errorHandler(me.getLang('autoupload.exceedTypeError'));

        return;

      }

      /* 创建Ajax并提交 */

      var xhr = new XMLHttpRequest(),

        fd = new FormData(),

        params = utils.serializeParam(me.queryCommandValue('serverparam')) || '',

        url = utils.formatUrl(actionUrl + (actionUrl.indexOf('?') == -1 ? '?' '&') + params);

      fd.append(fieldName, file, file.name || ('blob.' + file.type.substr('image/'.length)));

      fd.append('type''ajax');

      xhr.open("post", url, true);

      var accessToken=JSON.parse(window.sessionStorage.getItem("pigx-access_token")).content;

      var token = accessToken || '';

      xhr.setRequestHeader('Authorization''Bearer '+token);

      xhr.setRequestHeader('X-DOMAIN', window.location.host);

      xhr.setRequestHeader("X-Requested-With""XMLHttpRequest");

      xhr.addEventListener('load'function (e) {

        try {

          var json = (new Function("return " + utils.trim(e.target.response)))();

          if (json.state == 'SUCCESS' && json.url) {

            successHandler(json);

          else {

            errorHandler(json.state);

          }

        catch (er) {

          errorHandler(me.getLang('autoupload.loadError'));

        }

      });

      xhr.send(fd);

    }

  

4、在后台的过滤器中进行处理,针对接收到的额外参数,

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

@Override

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        //百度编辑器,上传图片时会使用form提交,无法设置header,so,修改如下代码

        if(((HttpServletRequest) request).getRequestURI().contains("ueditorConfig") && StringUtils.isNotBlank(request.getParameter("_authorization")))

        {

            HttpHeaderRequestWrapper httpHeaderRequestWrapper = new HttpHeaderRequestWrapper((HttpServletRequest) request

                    , request.getParameter("_authorization")

                    ,request.getParameter("_domain"));

            //this.setDomain(httpHeaderRequestWrapper, (HttpServletResponse) response);

            chain.doFilter(httpHeaderRequestWrapper, response);

        }

        else{

            //this.setDomain((HttpServletRequest)request,(HttpServletResponse)response);

            chain.doFilter(request,response);

        }

        //请求完成还原线程变量的值

        log.info("还原线程变量中的值");

        //HostThreadLocalConstant.getDomian().set("");

    }

  5、重写 getHeaders 方法

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

private static class HttpHeaderRequestWrapper extends HttpServletRequestWrapper{

        private final String domain;

        private final String authorization;

        public HttpHeaderRequestWrapper(HttpServletRequest request,String authorization,String domain) {

            super(request);

            this.domain=domain;

            this.authorization="Bearer "+authorization;

        }

        @Override

        public String getHeader(String name) {

            if (name!=null &&

                    name.equals("X-DOMAIN") &&

                    super.getHeader("X-DOMAIN")==null) {

                return domain;

            }else if (name!=null &&

                    name.equals("Authorization") &&

                    super.getHeader("Authorization")==null) {

                return authorization;

            }else {

                return super.getHeader(name);

            }

        }

        @Override

        public Enumeration<String> getHeaders(String name) {

            List<String> values = Collections.list(super.getHeaders(name));

            if (name!=null && name.equals("Authorization") ) {

                values.add(authorization);

            }

            return Collections.enumeration(values);

        }

    }

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值