Session && Cookie

Before, i only knew session is used to store data in the server and cookie is used to store data in the Client. However, it is far from enough at work.

For example:

If the user is logged in, we need to use session to store user’s information. Meanwhile, the server **automatically **storedssessionid within cookie and sends the cookie to the Client. We can see the set_Cookie attribute in the response header. and the Cookie:JSESSIONID=.... attribute in the request header.

notice:

the programmer is not need to operate the sessionId in the cookie , the browser will automatically maintain cookie.

Unless the cookie is set by yourself.

A session is a way to bind a browser session to a session server side. If you use different browsers (or privacy mode) you should be served a new session.

method : add cookie in the back end on your own initiative

response.setContentType("text/html;charset=utf-8");

HttpSession session = request.getSession();
session.setAttribute("data", "saveDat");
//save sessionid in cookie

Cookie cookie = new Cookie("JSESSION", session.getId());

//set a valid time

cookie.setMaxAge(60*20);

response.addCookie(cookie);



//when its first time to create session in the client, the server will create a new Session. or get the old sessionId.
String data = (String)request.getSession().getAttribute("data");

Properties: name, value, maxAge, secure, path, domain, comment, version HttpOnly.

maxAge: valid time. unit: second. if the value is negative number, it means the cookie is temporary . When the browser closes, the cookie is invalid. if the value is equal to 0, it means the cookie will be deleted. The default value is -1

secure: The HTTP Protocol is not only stateless, but also insecure. The data using HTTP Protocol spreads directly on the network without any encryption. when cookie.setSecure(true), the browser will spread the data with some secure protocols like SSL and HTTPS notice: it does not encrypt cookie content.

The following code will output all cookies

<script>document.write(document.cookie);</script>

so we can set HttpOnly property so that js can not read cookie . It can effectively prevent XSS attack

reference:

set httpOnlyattribute using Filter

session hijack

distributed session and session theory

Cross-origin resource sharing (CORS)

For security reasons, browsers prohibit AJAX calls to resource residing outside the current origin. Cross-origin resource sharing (CORS) is a W3C specification implemented by most browsers that allows you to specify in a flexible way what kind of cross domain requests are authorized, instead of using some less secured and less powerful hacks like IFRAME or JSONP ——–spring website && CORS

Three key points: the same protocol, the same port , the same domain.

W3C specification

Access-Control-Allow-Origin : return the value the origin request header, “*”, “null”.

​ notice: string “null”

Access-Control-Allow-Credentials: indicate whether the response to request can be exposed.

Access-Control-Max-Age: valid time

Access-Control-Allow-Methods : POST, GET , OPTIONS etc. notice : use OPTIONS method for preflight request.

……..

about preflight request —chinese description

how to do?

solution 1: rewrite route did not try it…

solution 2: set tomcat did not try it….

solution 3:

angular6: Interceptor

import { Injectable } from '@angular/core';
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpErrorResponse } from '@angular/common/http';
import {Observable, throwError} from 'rxjs';
import { catchError, retry } from 'rxjs/operators';
import { ActivatedRoute, Router } from '@angular/router';
import { CookieService } from "ngx-cookie-service";
@Injectable()
export class WithcredentialsInterceptor implements HttpInterceptor {
  constructor(
    private _cookieService:CookieService,
    private router: Router,

  ){}
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    var request;

    var temp = req.body;
    if(req.url.indexOf('backend/')>-1 && req.url.indexOf('backend/user/login') == -1){
      console.log(req.url,'cookie ', this._cookieService.get("SHGJSESSIONID"))
      temp.createTime = null;
      temp.updateTime = null;
      request = req.clone({
        withCredentials: true,
        setHeaders:{"Content-Type": "application/x-www-form-urlencoded"},
        // body:JSON.stringify(req.body)
        body:temp
      });
    }else{
      request = req;
    }
    return next.handle(request).pipe(retry(3)).pipe(catchError((err : any) =>{
           if (err instanceof HttpErrorResponse) {
            if (err.status === 401) {
              this.router.navigate(['/login']);
            }
            return  throwError(err);
        }
      }
    ));
}}
notice:withCredential: true; Content-Type: “application/x-www-form-urlencoded”.

if ContentType is application/json , it will not work. reason:important

spring boot:


public class SecurityInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        response.setHeader("Access-Control-Allow-Credentials","true");
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH");
        HttpSession session = request.getSession();

        if (session.getAttribute(WebSecurityConfig.SESSION_KEY) != null) {
            return true;
        } else {
            Cookie[] cookies = request.getCookies();
            if(cookies != null){
                for(Cookie cookie : cookies){
                    if(session.getId().equals(cookie.getValue())){
                        return true;
                    }
                }
            }


            response.setStatus(401);
//            response.setHeader("Cache-Control", "no-store");
//            response.setDateHeader("Expires", 0);
//            response.setHeader("WWW-authenticate", "Basic Realm=\"請先登錄系統\"");
            return false;
        }
//        return true;

    }

}



//we need to pass sessionId  to angular. because if the cookie is disabled.
// save store sessionId within cookie in the angular.
//reference:https://blog.csdn.net/fwk19840301/article/details/80675547
//https://blog.csdn.net/woshiyeguiren/article/details/79194003
notice:

www-authenticate: i do not suggest setting the attribute. if you set it and your response status is 4xx, the browsers will pop up a login prompt.

reference:

https://stackoverflow.com/questions/86105/how-can-i-suppress-the-browsers-authentication-dialog
這裏寫圖片描述

some people write the following:

@Configuration
public class WebSecurityConfig extends WebMvcConfigurerAdapter {

    /**
     * 登錄session key
     */
    public static final String SESSION_KEY = "user";

    @Bean
    public SecurityInterceptor getSecurityInterceptor() {
        return new SecurityInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        InterceptorRegistration addInterceptor = registry.addInterceptor(getSecurityInterceptor());

        // 排除配置
        addInterceptor.excludePathPatterns("/backend/user/login");
        addInterceptor.excludePathPatterns("/backend/user/success");
        addInterceptor.excludePathPatterns("/backend/user/loginout");
        addInterceptor.excludePathPatterns("/login**");

        // 攔截配置
        addInterceptor.addPathPatterns("/backend/**");
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("GET", "POST", "PUT", "OPTIONS", "DELETE", "PATCH")
                .allowCredentials(true).maxAge(3600);
    }
}

addCorsMappings method does not work. Access-Control-Allow-Origin should not be ‘*’; so need a filter or interceptor to set Access-Control-Allow-Origin

reference:

http://www.ruanyifeng.com/blog/2016/04/cors.html

https://blog.csdn.net/qq779446849/article/details/53102925

https://blog.csdn.net/saytime/article/details/74937204

BUG

Because Content-Type is application/x-www-form-urlencoded,

For application/x-www-form-urlencoded, the body of the HTTP message sent to the server is essentially one giant query string – name/value pairs are separated by the ampersand (&), and names are separated from values by the equals symbol (=). An example of this would be:

MyVariableOne=ValueOne&MyVariableTwo=ValueTwo

When you send the value encrypted by base64 with jsonString format, you may meet a parse bug.

example:

     var data={
           password: btoa((this.validateForm.controls['password'].value)),
           oldPassword: btoa((this.validateForm.controls['oldPassword'].value)),
           userName: this.username
        }
          this.indexService.changePassword(data).subscribe(
          (response :any) =>{
            this.isOkLoading = false;
            this.isVisible = false;
            if(response.status == environment.SUCCESS_STATUS){

              this.router.navigate(["login"]);
            }else{
              this.validateForm.reset();
              this._message.error("修改失敗");
            }
          }
        )
    //angular6  base64  ---btoa

when the password is 1234567 , the value encrypted by base64 will end with the double equals symbols ( = =),

and the browsers will parse == into :=
這裏寫圖片描述

這裏寫圖片描述
so i have to do this:

var data ="password="+btoa((this.validateForm.controls['password'].value))+"&"+"oldPassword="+btoa((this.validateForm.controls['oldPassword'].value))
             +"&" +"userName="+this.username;

and the browsers will parse the value into key/value pairs.

like :

FormData:

password:....

oldPassWord: .....

userName:.....
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章