爱奇艺扫码授权登录,爱奇艺登录二维码在哪

首页 > 大全 > 作者:YD1662022-12-19 00:44:10

第2章 授权码模式实战

在明白了Oauth2.0到底是个什么玩意儿,以及它的四种模式之后,接下来我们通过SpringSecurity来实现一下授权码模式,这种模式是市面上用的最广的。项目框架依然是以mall这个项目为主。但是会创建一个单独的认证服务器模块(mall-oauth2)和资源服务器模块(mall-resource)。

2.1 认证服务器

认证服务器是服务提供者专门用来处理认证授权的服务器,主要负责获取用户授权并颁发token,以及完成后续的token认证工作。认证部分功能主要由spring security 负责,授权则由oauth2负责。

2.1.1 项目搭建

创建一个springboot项目 mall-oauth2项目,配置pom

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <artifactId>mall</artifactId> <groupId>com.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <groupId>com.example</groupId> <artifactId>mall-oauth2</artifactId> <version>0.0.1-SNAPSHOT</version> <name>mall-oauth2</name> <description>认证服务器</description> <properties> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--mysql驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <!--druid--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> </dependency> <!--mybatis-plus--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency> </dependencies> </project>2.1.2 表结构设计

1.在oauth2库中增加表结构

DROP TABLE IF EXISTS `oauth_access_token`; CREATE TABLE `oauth_access_token` ( `token_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `token` blob NULL, `authentication_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `user_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `client_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `authentication` blob NULL, `refresh_token` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; DROP TABLE IF EXISTS `oauth_client_details`; CREATE TABLE `oauth_client_details` ( `client_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `resource_ids` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `client_secret` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `scope` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `authorized_grant_types` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `web_server_redirect_uri` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `authorities` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `access_token_validity` int(11) NULL DEFAULT NULL, `refresh_token_validity` int(11) NULL DEFAULT NULL, `additional_information` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL, `autoapprove` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT 'false', PRIMARY KEY (`client_id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; DROP TABLE IF EXISTS `oauth_code`; CREATE TABLE `oauth_code` ( `code` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `authentication` blob NULL ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; DROP TABLE IF EXISTS `oauth_refresh_token`; CREATE TABLE `oauth_refresh_token` ( `token_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `token` blob NULL, `authentication` blob NULL ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; INSERT INTO oauth_client_details(client_id,resource_ids,client_secret,scope,authorized_grant_types,web_server_redirect_uri,autoapprove) VALUES('iqiyi','resource1','$2a$10$m7rm4duMVCXbRAC0YChzsu8irZmAngLRHwJpBzPZjtT72yDxRYHVC','all','authorization_code','https://www.iqiyi.com','true');

2.然后创建用户和角色表

-- ---------------------------- -- Table structure for permission -- ---------------------------- DROP TABLE IF EXISTS `permission`; CREATE TABLE `permission` ( `id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `parent_id` bigint(11) NULL DEFAULT NULL COMMENT '用户ID', `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '权限名字', `ename` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '权限名字', `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '请求路径', `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '描述', `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of permission -- ---------------------------- INSERT INTO `permission` VALUES (1, 0, '系统管理', 'System', '/', NULL, '2019-05-30 16:22:20', '2019-05-30 16:22:24'); INSERT INTO `permission` VALUES (2, 0, '用户管理', 'SystemUser', '/users', NULL, '2019-05-30 16:23:28', '2019-05-30 16:23:32'); INSERT INTO `permission` VALUES (3, 0, '查看用户', 'SystemUserView', NULL, NULL, '2019-05-30 16:24:29', '2019-05-30 16:24:33'); INSERT INTO `permission` VALUES (4, 0, '新增用户', 'SystemUserInsert', NULL, NULL, '2019-05-30 16:25:09', '2019-05-30 16:25:13'); INSERT INTO `permission` VALUES (5, 0, '编辑用户', 'SystemUserUpdate', NULL, NULL, '2019-05-30 16:25:53', '2019-05-30 16:25:57'); INSERT INTO `permission` VALUES (6, 0, '删除用户', 'SystemUserDelete', NULL, NULL, '2019-05-30 16:26:49', '2019-05-30 16:26:54'); -- ---------------------------- -- Table structure for role -- ---------------------------- DROP TABLE IF EXISTS `role`; CREATE TABLE `role` ( `id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `parent_id` bigint(20) NULL DEFAULT NULL COMMENT '父类ID', `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '角色名字', `ename` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '角色名字', `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '描述', `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of role -- ---------------------------- INSERT INTO `role` VALUES (1, 0, '超级管理员', 'ADMIN', NULL, '2019-05-30 16:09:53', '2019-05-30 16:09:57'); -- ---------------------------- -- Table structure for role_permission -- ---------------------------- DROP TABLE IF EXISTS `role_permission`; CREATE TABLE `role_permission` ( `id` bigint(11) NOT NULL COMMENT '主键ID', `role_id` bigint(11) NULL DEFAULT NULL COMMENT '角色ID', `permission_id` bigint(11) NULL DEFAULT NULL COMMENT '权限ID', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of role_permission -- ---------------------------- INSERT INTO `role_permission` VALUES (1, 1, 1); INSERT INTO `role_permission` VALUES (2, 1, 2); INSERT INTO `role_permission` VALUES (3, 1, 3); INSERT INTO `role_permission` VALUES (4, 1, 4); INSERT INTO `role_permission` VALUES (5, 1, 5); INSERT INTO `role_permission` VALUES (6, 1, 6); -- ---------------------------- -- Table structure for my_user -- ---------------------------- DROP TABLE IF EXISTS `my_user`; CREATE TABLE `my_user` ( `id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `username` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '用户名', `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '密码', `gender` int(2) NULL DEFAULT NULL COMMENT '性别(1男 2女)', `email` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '邮箱', `create_time` datetime(0) NULL DEFAULT NULL COMMENT '用户创建时间', `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', `removed` int(2) NULL DEFAULT NULL COMMENT '是否删除(1删除0未删除)', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of my_user -- ---------------------------- INSERT INTO `my_user` VALUES (1, 'admin', '$2a$10$BDRAkgioU9jqN8eNVrRcluQd9GcocNv3EB8VfdKYfW8iR3vSbY3pW', 1, NULL, '2019-05-30 15:53:45', '2019-05-30 15:53:51', 0); -- ---------------------------- -- Table structure for user_role -- ---------------------------- DROP TABLE IF EXISTS `user_role`; CREATE TABLE `user_role` ( `id` bigint(11) NOT NULL COMMENT '主键ID', `user_id` bigint(11) NULL DEFAULT NULL COMMENT '用户主键', `role_id` bigint(11) NULL DEFAULT NULL COMMENT '角色ID', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of user_role -- ---------------------------- INSERT INTO `user_role` VALUES (1, 1, 1); SET FOREIGN_KEY_CHECKS = 1;2.1.3 配置

1.配置文件

# 应用名称 server.port=7070 spring.application.name=mall-oauth2 spring.thymeleaf.cache=false spring.datasource.druid.url=jdbc:mysql://192.168.8.74:3306/oauth2?useUnicode=true&characterEncoding=utf-8&useSSL=false spring.datasource.druid.username=root spring.datasource.druid.password=123456 spring.datasource.druid.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.druid.initial-size=30 spring.datasource.druid.max-active=100 spring.datasource.druid.min-idle=10 spring.datasource.druid.max-wait=60000 spring.datasource.druid.time-between-eviction-runs-millis=60000 spring.datasource.druid.min-evictable-idle-time-millis=300000 spring.datasource.druid.validation-query=SELECT 1 FROM DUAL spring.datasource.druid.test-while-idle=true spring.datasource.druid.test-on-borrow=false spring.datasource.druid.test-on-return=false spring.datasource.druid.filters=stat,wall mybatis-plus.configuration.map-underscore-to-camel-case=true mybatis-plus.configuration.auto-mapping-behavior=full mybatis-plus.mapper-locations=classpath*:mapper/*Mapper.xml

2.开启Spring Security 安全配置

创建WebSecurityConfig 继承WebSecurityConfigurerAdapter

@Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Bean public BCryptPasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); } @Override @Bean public AuthenticationManager authenticationManager() throws Exception { return super.authenticationManager(); } }

通过@EnableWebSecurity 开启Spring Security配置,继承WebSecurityConfigurerAdapter的方法,实现个性化配置。如果使用内存配置用户,可以重写其中的configure方法进行配置,由于我们使用数据库中的用户信息,所以不需要在这里进行配置。并且采用认证服务器和资源服务器分离,也不需要在这里对服务资源进行权限的配置。

在类中创建了两个Bean,分别是用于处理认证请求的认证管理器AuthenticationManager,以及配置全局统一使用的密码加密方式BCryptPasswordEncoder,它们会在认证服务中被使用。

3.创建认证服务配置类

@Configuration @EnableAuthorizationServer public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private AuthenticationManager authenticationManager; //认证管理器 @Autowired private BCryptPasswordEncoder passwordEncoder;//密码加密方式 @Autowired private DataSource dataSource; // 注入数据源 @Autowired private UserDetailsService userDetailsService; //自定义用户身份认证 @Bean public ClientDetailsService jdbcClientDetailsService(){ //将client信息存储在数据库中 return new JdbcClientDetailsService(dataSource); } @Bean public TokenStore tokenStore(){ //对token进行持久化存储在数据库中,数据存储在oauth_access_token和oauth_refresh_token return new JdbcTokenStore(dataSource); } @Bean public AuthorizationCodeServices authorizationCodeServices() { //加入对授权码模式的支持 return new JdbcAuthorizationCodeServices(dataSource); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { //设置客户端的配置从数据库中读取,存储在oauth_client_details表 clients.withClientDetails(jdbcClientDetailsService()); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints .tokenStore(tokenStore())//token存储方式 .authenticationManager(authenticationManager)// 开启密码验证,来源于 WebSecurityConfigurerAdapter .userDetailsService(userDetailsService)// 读取验证用户的信息 .authorizationCodeServices(authorizationCodeServices()) .setClientDetailsService(jdbcClientDetailsService()); } @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { // 配置Endpoint,允许请求,不被Spring-security拦截 security.tokenKeyAccess("permitAll()") // 开启/oauth/token_key 验证端口无权限访问 .checkTokenAccess("isAuthenticated()") // 开启/oauth/check_token 验证端口认证权限访问 .allowFormAuthenticationForClients()// 允许表单认证 .passwordEncoder(passwordEncoder); // 配置BCrypt加密 } }

在类中,通过@EnableAuthorizationServer 注解开启认证服务,通过继承父类AuthorizationServerConfigurerAdapter,对以下信息进行了配置:

ClientDetailsServiceConfigurer:配置客户端服务,这里我们通过JdbcClientDetailsService从数据库读取相应的客户端配置信息,进入源码可以看到客户端信息是从表oauth_client_details中拉取。

AuthorizationServerEndpointsConfigurer:用来配置授权(authorization)以及令牌(token)的访问端点,以及令牌服务的配置信息。该类作为一个装载类,装载了Endpoints所有的相关配置。

AuthorizationServerSecurityConfigurer:配置令牌端点(endpoint)的安全约束,OAuth2开放了端点用于检查令牌,/oauth/check_token和/oauth/token_key这些端点默认受到保护,在这里配置可被外部调用。

4.采用从数据库中获取用户信息的方式进行身份验证

@Service public class UserDetailServiceImpl implements UserDetailsService { @Autowired private UserService userService; @Autowired private PermissionService permissionService; @Override public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException { MyUser myUser = userService.getUserByUserName(userName); if (myUser==null){ throw new UsernameNotFoundException("username : " userName " is not exist"); } List<GrantedAuthority> authorities=new ArrayList<>(); //获取用户权限 List<Permission> permissions = permissionService.getByUserId(myUser.getId()); permissions.forEach(permission->{ authorities.add(new SimpleGrantedAuthority(permission.getEname())); }); return new User(myUser.getUsername(),myUser.getPassword(),authorities); } }

创建UserDetailServiceImpl 实现UserDetailsService接口,并实现loadUserByUsername方法,根据用户名从数据库查询用户信息及权限。

5.创建MyUser和Permission等实体类,具体参考代码

2.1.4 启动服务

首先发起请求获取授权码(code),直接访问下面的url:

http://localhost:7070/oauth/authorize?client_id=iqiyi&response_type=code

首先会重定向到登录验证页面,因为之前的url中只明确了第三方应用的身份,这里要确定第三方应用要请求哪一个用户的授权。输入数据库表user中配置的用户信息 admin/123456:

爱奇艺扫码授权登录,爱奇艺登录二维码在哪(5)

注意url中请求的参数必须和在数据库中的表oauth_client中配置的相同,如果不存在或信息不一致都会报错,在参数填写错误时会产生如下报错信息:

爱奇艺扫码授权登录,爱奇艺登录二维码在哪(6)

如果参数完全匹配,会请求用户向请求资源的客户端client授权,因为我数据库的autoapprove字段设置为true了,所以直接会进行授权。并且页面会跳转到redirect_uri定义的地址,并在uri后面带上code授权码。

爱奇艺扫码授权登录,爱奇艺登录二维码在哪(7)

这样,用户的登录和授权的操作都在浏览器中完成了,接下来我们需要获取令牌,发送post请求到/oauth/token接口,使用授权码获取access_token。在发送请求时,需要在请求头中包含clientId和clientSecret,并且携带参数 grant_type、code、redirect_uri,这里会对redirect_uri做二次验证:

爱奇艺扫码授权登录,爱奇艺登录二维码在哪(8)

上一页123下一页

栏目热文

文档排行

本站推荐

Copyright © 2018 - 2021 www.yd166.com., All Rights Reserved.