oauth2 未登錄用戶訪問時自動跳轉到登錄頁面,並記錄當前頁面,登陸后自動跳回


實現不復雜,但比較繁瑣,建議結合項目查看

首先,我們的登錄驗證基於網關服務,如果網關沒有檢測到cookie中由jti或者沒有找到對應的jwt,我們認為用戶沒有登錄

此時要跳轉到登錄頁面

網關是基於過濾器實現的,過濾器為

@Component
public class AuthFilter implements GlobalFilter, Ordered {
    @Autowired
    private AuthService authService;

//定義跳往登錄頁面的controller
private static final String LOGIN_URL ="http://localhost:8001/api/oauth/toLogin"; @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { //過濾調用業務的請求,判斷現在是否已經登錄(cookie中有沒有jti),如果以登錄,向請求頭中加入jwt令牌 ServerHttpResponse response = exchange.getResponse(); ServerHttpRequest request = exchange.getRequest(); //判斷當前的請求路徑是否是登錄請求,如果是,直接放行 String path = request.getURI().getPath(); if("/api/oauth/login".equals(path)||! UrlFilter.hasAuthorize(path)){ //直接放行 return chain.filter(exchange); } //從cookie中獲取jti,如果jti不存在,拒絕訪問 String jti = authService.getJtiFromCookie(request); if(StringUtils.isEmpty(jti)){ //如果jti為空,拒絕訪問 // response.setStatusCode(HttpStatus.UNAUTHORIZED); // return response.setComplete(); //如果jti為空,跳轉登錄頁面 from就是當前的網頁地址,待會還要跳回來 return this.toLoginPage(LOGIN_URL+"?FROM="+request.getURI().getPath(),exchange); } //從redis中獲取jwt令牌,如果該值不存在,拒絕本次訪問 String jwt = authService.getJwtFromRedis(jti); if(StringUtils.isEmpty(jwt)){ //如果jwt為空,拒絕訪問 // response.setStatusCode(HttpStatus.UNAUTHORIZED); // return response.setComplete(); //如果jwt為空,跳轉到登錄頁面 from就是當前的網頁地址,待會還要跳回來 return this.toLoginPage(LOGIN_URL?FROM="+request.getURI().getPath(),exchange); } //對當前的請求對象進行增強,讓他攜帶令牌信息,因為微服務里如果引入了oauth2,會對令牌進行校驗 request.mutate().header("Authorization","Bearer "+jwt); System.out.println("令牌為"+jwt); return chain.filter(exchange); } //跳轉到的登陸頁面 private Mono<Void> toLoginPage(String loginUrl, ServerWebExchange exchange) { ServerHttpResponse response = exchange.getResponse(); response.setStatusCode(HttpStatus.SEE_OTHER); //這個狀態碼的意思是跳轉 response.getHeaders().set("Location",loginUrl); return response.setComplete(); } @Override public int getOrder() { return 0; } }

網關發請求到跳轉controller,這是controller

@Controller
@RequestMapping("/oauth")
public class AuthController {
    @Value("${auth.clientId}")
    private String clientId;
    @Value("${auth.clientSecret}")
    private String clientSecret;
    @Value("${auth.cookieDomain}")
    private String cookieDomain;  //值為localhost
    @Value("${auth.cookieMaxAge}")
    private int cookieMaxAge;  //值為-1

    @Autowired
    private AuthService authService;

    @RequestMapping("/login")
    @ResponseBody
    public Result login(String username, String password, HttpServletResponse response){
        //校驗相關的參數
        if(StringUtils.isEmpty(username)){
            throw new RuntimeException("請輸入用戶名");
        }
        if(StringUtils.isEmpty(password)){
            throw new RuntimeException("請輸入密碼");
        }

        //申請令牌
        AuthToken authToken = authService.login(username, password, clientId, clientSecret);
        //將jti的值存入cookie中
        this.saveJtiToCookie(authToken.getJti(),response);
        //返回結果
        return new Result(true, StatusCode.OK,"登錄成功",authToken.getJti());
    }

    //將jwt令牌的短標識jti存到cookie中
    private void saveJtiToCookie(String jti, HttpServletResponse response) {
        CookieUtil.addCookie(response,cookieDomain,"/","uid",jti,cookieMaxAge,false);//httpOnly=true時,將無法通過js讀取cookie,有利於防止攻擊
    }

    //跳轉到登錄頁面
    @RequestMapping("/toLogin")
    //參數用於跳回登陸前的頁面,required表示非必須
    public String toLogin(@RequestParam(value = "FROM",required = false,defaultValue = "") String from, Model model){
        model.addAttribute("from",from);
        return "login";//這是指login.html文件 }

}

在login.html中的js中,定義參數接收model中的from,並定義登錄成功后自動跳轉

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM