0


【开源项目】Sa-Token快速登录(使用+源码解析)

什么是Sa-Token

官网:https://sa-token.dev33.cn

Sa-Token 是一个轻量级 Java 权限认证框架,主要解决:**

登录认证

权限认证

Session会话

单点登录

OAuth2.0

微服务网关鉴权

** 等一系列权限相关问题。
在这里插入图片描述

快速使用

引入Maven依赖

<!-- web支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--Sa-Token-Quick-Login 插件 --><dependency><groupId>cn.dev33</groupId><artifactId>sa-token-quick-login</artifactId><version>1.33.0</version></dependency>

配置参数

server:port:8080# Sa-Token-Quick-Login 配置sa:# 登录账号name: admin
  # 登录密码pwd:123456# 是否自动随机生成账号密码 (此项为true时, name与pwd失效)auto:false# 是否开启全局认证(关闭后将不再强行拦截)auth:true# 登录页标题title: Charles Index 登录
  # 是否显示底部版权信息copr:true# 指定拦截路径include: /**# 指定排除路径exclude: /test

编写Controller

@RestControllerpublicclassTestController{/**
     * 不需要认证
     *
     * @return
     */@GetMapping("test")publicStringtest(){return"test";}/**
     * 需要认证
     *
     * @return
     */@GetMapping("test1")publicStringtest1(){return"test1";}}

测试

由于没有登录,被拦截了,到了登录页面

源码解析

  1. 引入sa-token-quick-login,会加载jar包中的spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.dev33.satoken.quick.SaQuickInject
  1. SaQuickInject类上面注解是@Import({SaQuickController.class, SaQuickRegister.class}),所以会添加SaQuickControllerSaQuickRegister
  2. SaQuickController主要是提供登录页面和提供登录接口
@ControllerpublicclassSaQuickController{publicSaQuickController(){}@GetMapping({"/saLogin"})publicStringsaLogin(HttpServletRequest request){
        request.setAttribute("cfg",SaQuickManager.getConfig());return"sa-login.html";}@PostMapping({"/doLogin"})@ResponseBodypublicSaResultdoLogin(String name,String pwd){if(!SaFoxUtil.isEmpty(name)&&!SaFoxUtil.isEmpty(pwd)){SaQuickConfig config =SaQuickManager.getConfig();if(name.equals(config.getName())&& pwd.equals(config.getPwd())){StpUtil.login(config.getName());returnSaResult.get(200,"ok",StpUtil.getTokenInfo());}else{returnSaResult.get(500,"账号或密码输入错误",(Object)null);}}else{returnSaResult.get(500,"请输入账号和密码",(Object)null);}}}
  1. SaQuickRegister是核心,提供了SaServletFilterSaServletFilter用来做拦截认证。
@ConfigurationpublicclassSaQuickRegister{publicSaQuickRegister(){}@Bean@ConfigurationProperties(
        prefix ="sa")publicSaQuickConfiggetSaQuickConfig(){returnnewSaQuickConfig();}@Bean@Order(-101)publicSaServletFiltergetSaServletFilter(){return(newSaServletFilter()).addInclude(newString[]{"/**"}).addExclude(newString[]{"/favicon.ico","/saLogin","/doLogin","/sa-res/**"}).setAuth((obj)->{SaRouter.match(SaQuickManager.getConfig().getInclude().split(",")).notMatch(SaQuickManager.getConfig().getExclude().split(",")).check((r)->{if(SaQuickManager.getConfig().getAuth()&&!StpUtil.isLogin()){SaHolder.getRequest().forward("/saLogin");SaRouter.back();}});}).setError((e)->{return e.getMessage();});}}
  1. 访问http://localhost:8080/test,看下SaServletFilter是如何放行的。
// cn.dev33.satoken.filter.SaServletFilter#doFilterpublicvoiddoFilter(ServletRequest request,ServletResponse response,FilterChain chain)throwsIOException,ServletException{try{SaRouter.match(this.includeList).notMatch(this.excludeList).check((r)->{this.beforeAuth.run((Object)null);this.auth.run((Object)null);});}catch(StopMatchException var6){}catch(Throwable var7){String result = var7 instanceofBackResultException? var7.getMessage():String.valueOf(this.error.run(var7));if(response.getContentType()==null){
                response.setContentType("text/plain; charset=utf-8");}

            response.getWriter().print(result);return;}

        chain.doFilter(request, response);}
  1. 该auth方法是在SaQuickRegister类中定义的。因为/test是在配置文件中定义的,所以在执行SaRouter.match(SaQuickManager.getConfig().getInclude().split(",")).notMatch(SaQuickManager.getConfig().getExclude().split(","))后,SaRouterStaff中的isHit变量为false,所以SaRouterStaff#check()不需要执行。
publicSaRouterStaffnotMatch(String... patterns){if(this.isHit){this.isHit =!SaRouter.isMatchCurrURI(patterns);}returnthis;}
  1. test1方法由于不在exclude配置中,所以会执行SaRouterStaff#check()。该方法中主要有两个判断,SaQuickManager.getConfig().getAuth()StpUtil.isLogin() == false。配置中的auth设置为true,所以第一个判断为true。
  2. StpUtil.isLogin()用来判断是否登录。跟踪到获取到token的方法,获取不到token,返回false,跳转到saLogin页面。
getTokenValueNotCut:249, StpLogic (cn.dev33.satoken.stp)
getTokenValue:201, StpLogic (cn.dev33.satoken.stp)
getLoginIdDefaultNull:746, StpLogic (cn.dev33.satoken.stp)
isLogin:659, StpLogic (cn.dev33.satoken.stp)
isLogin:282, StpUtil (cn.dev33.satoken.stp)
  1. 登录方法,SaQuickController#doLogin()。创造token,并且存储在客户端。
login:331, StpLogic (cn.dev33.satoken.stp)
login:293, StpLogic (cn.dev33.satoken.stp)
login:135, StpUtil (cn.dev33.satoken.stp)
doLogin:53, SaQuickController (cn.dev33.satoken.quick.web)
publicvoidlogin(Object id,SaLoginModel loginModel){// 1、创建会话 String token =createLoginSession(id, loginModel);// 2、在当前客户端注入Token setTokenValue(token, loginModel);}
  1. 存储在客户端。先保留一份在SaStorage,再存入cookie。
publicvoidsetTokenValue(String tokenValue,SaLoginModel loginModel){if(SaFoxUtil.isEmpty(tokenValue)){return;}// 1. 将 Token 保存到 [存储器] 里  setTokenValueToStorage(tokenValue);// 2. 将 Token 保存到 [Cookie] 里 if(getConfig().getIsReadCookie()){setTokenValueToCookie(tokenValue, loginModel.getCookieTimeout());}// 3. 将 Token 写入到响应头里 if(loginModel.getIsWriteHeaderOrGlobalConfig()){setTokenValueToResponseHeader(tokenValue);}}
  1. 登录的时候,从cookie中获取token,判断是否过期,如果能获取loginId,则判断是登录状态,SaTokenDaoDefaultImpl#get
@OverridepublicStringget(String key){clearKeyByTimeout(key);return(String)dataMap.get(key);}
标签: 开源 java spring

本文转载自: https://blog.csdn.net/qq_42985872/article/details/128581188
版权归原作者 秋装什么 所有, 如有侵权,请联系我们删除。

“【开源项目】Sa-Token快速登录(使用+源码解析)”的评论:

还没有评论