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