大家好,今天来为大家解答授权码网站api源码分享这个问题的一些问题点,包括授权码原理也一样很多人还不知道,因此呢,今天就来为大家分析分析,现在让我们一起来看看吧!如果解决了您的问题,还望您关注下本站哦,谢谢~
前置知识
我们将采用Nacos作为注册中心,Gateway作为网关,使用Sa-Token提供的微服务权限解决方案,此方案是基于之前的解决方案改造的
应用架构
还是和之前方案差不多的思路,认证服务负责登录处理,网关负责登录认证和权限认证,其他API服务负责处理自己的业务逻辑。为了能在多个服务中共享Sa-Token的Session,所有服务都需要集成Sa-Token和Redis。
micro-sa-token-common:通用工具包,其他服务公用的用户类UserDTO和通用返回结果类CommonResult被抽取到了这里。micro-sa-token-gateway:网关服务,负责请求转发、登录认证和权限认证。micro-sa-token-auth:认证服务,仅包含一个登录接口,调用Sa-Token的API实现。micro-sa-token-api:受保护的API服务,用户通过网关鉴权通过后可以访问该服务。
方案实现
接下来实现下这套解决方案,依次搭建网关服务、认证服务和API服务。
micro-sa-token-gateway
我们首先来搭建下网关服务,它将负责整个微服务的登录认证和权限认证。
除了通用的Gateway依赖,我们还需要在pom.xml中添加如下依赖,包括Sa-Token的Reactor响应式依赖,整合Redis实现分布式Session的依赖以及我们的micro-sa-token-common依赖;
<dependencies>\n<!–Sa-Token权限认证(Reactor响应式集成)–>\n<dependency>\n<groupId>cn.dev33</groupId>\n<artifactId>sa-token-reactor-spring-boot-starter</artifactId>\n<version>1.24.0</version>\n</dependency>\n<!–Sa-Token整合Redis(使用jackson序列化方式)–>\n<dependency>\n<groupId>cn.dev33</groupId>\n<artifactId>sa-token-dao-redis-jackson</artifactId>\n<version>1.24.0</version>\n</dependency>\n<!–提供Redis连接池–>\n<dependency>\n<groupId>org.apache.commons</groupId>\n<artifactId>commons-pool2</artifactId>\n</dependency>\n<!–micro-sa-token通用依赖–>\n<dependency>\n<groupId>com.macro.cloud</groupId>\n<artifactId>micro-sa-token-common</artifactId>\n<version>1.0.0</version>\n</dependency>\n</dependencies>
接下来修改配置文件application.yml,添加Redis配置和Sa-Token的配置,如果你看过之前那篇Sa-Token使用教程的话,基本就知道这些配置的作用了;
spring:\nredis:\ndatabase:0\nport:6379\nhost:localhost\npassword:\n\ntoken名称(同时也是cookie名称)\ntoken-name:Authorization\ntoken临时有效期(指定时间内无操作就视为token过期),单位秒\nactivity-timeout:-1\n在多人登录同一账号时,是否共用一个token(为false时每次登录新建一个token)\nis-share:false\n是否输出操作日志\nis-log:false\n是否从head中读取token\nis-read-head:true
添加Sa-Token的配置类SaTokenConfig,注入一个过滤器用于登录认证和权限认证,在setAuth方法中添加路由规则,在setError方法中添加鉴权失败的回调处理;
@Configuration\npublicclassSaTokenConfig{\n/**\n*注册Sa-Token全局过滤器\n*/\n@Bean\npublicSaReactorFiltergetSaReactorFilter(){\nreturnnewSaReactorFilter()\n//拦截地址\n.addInclude(&34;)\n//开放地址\n.addExclude(&34;)\n//鉴权方法:每次访问进入\n.setAuth(r->{\n//登录认证:除登录接口都需要认证\nSaRouter.match(&34;,&34;,StpUtil::checkLogin);\n//权限认证:不同接口访问权限不同\nSaRouter.match(&34;,()->StpUtil.checkPermission(&34;));\nSaRouter.match(&34;,()->StpUtil.checkPermission(&34;));\n})\n//setAuth方法异常处理\n.setError(e->{\n//设置错误返回格式为JSON\nServerWebExchangeexchange=SaReactorSyncHolder.getContent();\nexchange.getResponse().getHeaders().set(&34;,&34;);\nreturnSaResult.error(e.getMessage());\n});\n}\n}
扩展下Sa-Token提供的StpInterface接口,用于获取用户的权限,我们在用户登录以后会把用户信息存到Session中去,权限信息也会在里面,所以权限码只要从Session中获取即可。
/**\n*自定义权限验证接口扩展\n*/\n@Component\npublicclassStpInterfaceImplimplementsStpInterface{\n\n@Override\npublicList<String>getPermissionList(ObjectloginId,StringloginType){\n//返回此loginId拥有的权限码列表\nUserDTOuserDTO=(UserDTO)StpUtil.getSession().get(&34;);\nreturnuserDTO.getPermissionList();\n}\n\n@Override\npublicList<String>getRoleList(ObjectloginId,StringloginType){\n//返回此loginId拥有的角色码列表\nreturnnull;\n}\n\n}
micro-sa-token-auth
接下来我们来搭建下认证服务,只要集成Sa-Token并实现登录接口即可,非常简单。
首先在pom.xml中添加相关依赖,包括Sa-Token的SpringBoot依赖、整合Redis实现分布式Session的依赖以及我们的micro-sa-token-common依赖;
<dependencies>\n<!–Sa-Token权限认证–>\n<dependency>\n<groupId>cn.dev33</groupId>\n<artifactId>sa-token-spring-boot-starter</artifactId>\n<version>1.24.0</version>\n</dependency>\n<!–Sa-Token整合Redis(使用jackson序列化方式)–>\n<dependency>\n<groupId>cn.dev33</groupId>\n<artifactId>sa-token-dao-redis-jackson</artifactId>\n<version>1.24.0</version>\n</dependency>\n<!–提供Redis连接池–>\n<dependency>\n<groupId>org.apache.commons</groupId>\n<artifactId>commons-pool2</artifactId>\n</dependency>\n<!–micro-sa-token通用依赖–>\n<dependency>\n<groupId>com.macro.cloud</groupId>\n<artifactId>micro-sa-token-common</artifactId>\n<version>1.0.0</version>\n</dependency>\n</dependencies>
接下来修改配置文件application.yml,照抄之前网关的配置即可;
spring:\nredis:\ndatabase:0\nport:6379\nhost:localhost\npassword:\n\ntoken名称(同时也是cookie名称)\ntoken-name:Authorization\ntoken临时有效期(指定时间内无操作就视为token过期),单位秒\nactivity-timeout:-1\n在多人登录同一账号时,是否共用一个token(为false时每次登录新建一个token)\nis-share:false\n是否输出操作日志\nis-log:false\n是否从head中读取token\nis-read-head:true
在UserController中定义好登录接口,登录成功后返回Token,具体实现在UserServiceImpl类中;
/**\n*自定义Oauth2获取令牌接口\n*Createdbymacroon2020/7/17.\n*/\n@RestController\n@RequestMapping(&34;)\npublicclassUserController{\n@Autowired\nprivateUserServiceImpluserService;\n\n@RequestMapping(value=&34;,method=RequestMethod.POST)\npublicCommonResultlogin(@RequestParamStringusername,@RequestParamStringpassword){\nSaTokenInfosaTokenInfo=userService.login(username,password);\nif(saTokenInfo==null){\nreturnCommonResult.validateFailed(&34;);\n}\nMap<String,String>tokenMap=newHashMap<>();\ntokenMap.put(&34;,saTokenInfo.getTokenValue());\ntokenMap.put(&34;,saTokenInfo.getTokenName());\nreturnCommonResult.success(tokenMap);\n}\n}
在UserServiceImpl中添加登录的具体逻辑,首先验证密码,密码校验成功后,通知下Sa-Token登录的用户ID,然后把用户信息直接存储到Session中去;
/**\n*用户管理业务类\n*Createdbymacroon2020/6/19.\n*/\n@Service\npublicclassUserServiceImpl{\n\nprivateList<UserDTO>userList;\n\npublicSaTokenInfologin(Stringusername,Stringpassword){\nSaTokenInfosaTokenInfo=null;\nUserDTOuserDTO=loadUserByUsername(username);\nif(userDTO==null){\nreturnnull;\n}\nif(!SaSecureUtil.md5(password).equals(userDTO.getPassword())){\nreturnnull;\n}\n//密码校验成功后登录,一行代码实现登录\nStpUtil.login(userDTO.getId());\n//将用户信息存储到Session中\nStpUtil.getSession().set(&34;,userDTO);\n//获取当前登录用户Token信息\nsaTokenInfo=StpUtil.getTokenInfo();\nreturnsaTokenInfo;\n}\n}
这里有一点需要提醒下,Sa-Token的Session并不是我们平时理解的HttpSession,而是它自己实现的类似Session的机制。
micro-sa-token-api
接下来我们来搭建一个受保护的API服务,实现获取登录用户信息的接口和需要特殊权限才能访问的测试接口。
首先在pom.xml中添加相关依赖,和上面的micro-sa-token-auth一样;
<dependencies>\n<!–Sa-Token权限认证–>\n<dependency>\n<groupId>cn.dev33</groupId>\n<artifactId>sa-token-spring-boot-starter</artifactId>\n<version>1.24.0</version>\n</dependency>\n<!–Sa-Token整合Redis(使用jackson序列化方式)–>\n<dependency>\n<groupId>cn.dev33</groupId>\n<artifactId>sa-token-dao-redis-jackson</artifactId>\n<version>1.24.0</version>\n</dependency>\n<!–提供Redis连接池–>\n<dependency>\n<groupId>org.apache.commons</groupId>\n<artifactId>commons-pool2</artifactId>\n</dependency>\n<!–micro-sa-token通用依赖–>\n<dependency>\n<groupId>com.macro.cloud</groupId>\n<artifactId>micro-sa-token-common</artifactId>\n<version>1.0.0</version>\n</dependency>\n</dependencies>
接下来修改配置文件application.yml,照抄之前网关的配置即可;
spring:\nredis:\ndatabase:0\nport:6379\nhost:localhost\npassword:\n\ntoken名称(同时也是cookie名称)\ntoken-name:Authorization\ntoken临时有效期(指定时间内无操作就视为token过期),单位秒\nactivity-timeout:-1\n在多人登录同一账号时,是否共用一个token(为false时每次登录新建一个token)\nis-share:false\n是否输出操作日志\nis-log:false\n是否从head中读取token\nis-read-head:true
添加获取用户信息的接口,由于使用了Redis实现分布式Session,直接从Session中获取即可,是不是非常简单!
/**\n*获取登录用户信息接口\n*Createdbymacroon2020/6/19.\n*/\n@RestController\n@RequestMapping(&34;)\npublicclassUserController{\n\n@GetMapping(&34;)\npublicCommonResult<UserDTO>userInfo(){\nUserDTOuserDTO=(UserDTO)StpUtil.getSession().get(&34;);\nreturnCommonResult.success(userDTO);\n}\n\n}
添加需要api:test:hello权限访问的测试接口,预置的admin用户拥有该权限,而macro用户是没有的。
/**\n*测试接口\n*Createdbymacroon2020/6/19.\n*/\n@RestController\n@RequestMapping(&34;)\npublicclassTestController{\n\n@GetMapping(&34;)\npublicCommonResulthello(){\nreturnCommonResult.success(&34;);\n}\n\n}
功能演示
三个服务搭建完成后,我们用Postman来演示下微服务的认证授权功能。
首先启动Nacos和Redis服务,然后再启动micro-sa-token-gateway、micro-sa-token-auth和micro-sa-token-api服务,启动顺序无所谓;直接通过网关访问登录接口获取Token,访问地址:http://localhost:9201/auth/user/login通过网关访问API服务,不带Token调用获取用户信息的接口,无法正常访问,访问地址:http://localhost:9201/api/user/info通过网关访问API服务,带Token调用获取用户信息的接口,可以正常访问;通过网关访问API服务,使用macro用户访问需api:test:hello权限的测试接口,无法正常访问,访问地址:http://localhost:9201/api/test/hello登录切换为admin用户,该用户具有api:test:hello权限;通过网关访问API服务,使用admin用户访问测试接口,可以正常访问。
总结
对比之前使用SpringSecurity的微服务权限解决方案,Sa-Token的解决方案更简单、更优雅。使用Security我们需要定义鉴权管理器、分别处理未认证和未授权的情况、还要自己定义认证和资源服务器配置,使用非常繁琐。而使用Sa-Token,只要在网关上配置过滤器实现认证和授权,然后调用API实现登录及权限分配即可。具体区别可以参考下图。
项目源码地址
https://github.com/macrozheng/springcloud-learning/tree/master/micro-sa-token
关于授权码网站api源码分享的内容到此结束,希望对大家有所帮助。
