美文网首页
前后端分离方式下,跨域使用cookie进行安全认证

前后端分离方式下,跨域使用cookie进行安全认证

作者: JohnYuCN | 来源:发表于2021-01-20 14:41 被阅读0次

    说明:以SpringBoot为后端,React和Fetch为前端,举例说明。

    零:三条军规:

    以后的论述都是为绕过军规的手段:

    • 军规一: 浏览器环境中无法利用JS 获取跨域后端的 Set-Cookie响应头
    • 军规二: 浏览器环境中无法使用直接使用JS异步发送Cookie请求头
    • 军规三:浏览器环境中,默认不可以使用JS访问document.cookie对象

    一、 服务器端的设置:

    必须在跨域设置中加入:

    1. 设置响应头 Access-Control-Allow-Credentials: true, 使XHR引擎可以访问到document.cookie。
    2. 设置响应头: Access-Control-Allow-Origin: http://localhost:3001,需要指定前端的域,不能使用默认的 ' * '
    3. 取消cookie的httpOnly属性,使JS可以访问到cookie:
      application.yml
    server:
      servlet:
        session:
          cookie:
            http-only: false
    

    以上设置必然是以降低安全性为代价

    二、客户端设置:

    1. fetch 中加入{credentials: 'include'}
    2. xhr和axios中加入: xhr.withCredentials = true;{withCredentials:true}
      此举可以在异步请求中,把document.cookie中的信息,以Cookie头的形式发出
    3. jquery中加入:
                $.ajax({
                    url: "http://localhost:8080/test1",
                    crossDomain: true,
                    xhrFields: {
                        withCredentials: true
                    }
                });
    

    三、客户端代码示例

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8" />
        <title>Add React in One Minute</title>
      </head>
      <body>
        <div id="app"></div>
    
        <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
        <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
    
        <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
        <script type="text/babel">
          class App extends React.Component {
            //1. 登录成功,服务器端返回Set-Cookie: <Session ID>,会以JSESSIONID=XXX存入document.cookie中,
            //2. credentials: 'include' 的第一个含义:允许JS 访问document.cookie,但注意服务器两个条件的配合:
                // (1)Access-Control-Allow-Credentials:true ,Access-Control-Allow-Origin: <不为*>
                // (2)取消cookie中的 http-only属性
            _login=()=>{
                fetch('http://localhost:8080/login?uname=john&password=123',
                {credentials: 'include'})
                .then(resp=>resp.text())
                .then(info=>alert(info))
                
            }
            //1. 这是登录成功后的请求,应用了credentials: 'include'的第二个含义,即:从document.cookie中获取信息,加入请求头中Cookie: <XXX>
            //2. 此处仍然需要服务器的两个条件配合
            _info=()=>{
                fetch('http://localhost:8080/info',
                {method:'GET',credentials: 'include'})
                .then(resp=>resp.text())
                .then(info=>alert(info))
            }
    
            render() {
               return (
                  <div>
                    <button onClick={this._login}>登录</button>
                    <button onClick={this._info}>
                      获取信息
                    </button>
                  </div>
                )
            }
          }
          ReactDOM.render(<App/>, document.querySelector('#app'));
        </script>
      </body>
    </html>
    

    四、服务器端代码:

    package sso;
    
    import org.springframework.web.bind.annotation.CrossOrigin;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import javax.servlet.http.HttpSession;
    import java.util.Optional;
    
    @RestController
    @CrossOrigin(allowCredentials = "true",origins = "http://localhost:3001")
    public class SsoController {
        @RequestMapping("/login")
        public String login(String uname, String password, HttpSession session){
            if("john".equals(uname) && "123".equals(password)){
                session.setAttribute("username",uname);
                return "suc";
            }
            else {
                return "fail";
            }
        }
        @RequestMapping("/info")
        public String info(HttpSession session){
           String info= Optional.
                    ofNullable((String)session.getAttribute("username"))
                    .orElse("fail");
            return info;
        }
    }
    

    相关文章

      网友评论

          本文标题:前后端分离方式下,跨域使用cookie进行安全认证

          本文链接:https://www.haomeiwen.com/subject/zbrkzktx.html