搭建一套自己的验证授权及资源访问服务
Posted dingwen_blog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了搭建一套自己的验证授权及资源访问服务相关的知识,希望对你有一定的参考价值。
学习小项目系列目录
项目1:SSM + Layui + Mysql8 公司测评系统
项目2:SpringBoot+Vue+ Mysql8 大学社团管理系统
项目3:搭建自用单点OOS服务
项目4:搭建一套自己的验证授权及资源访问服务
本文的记录了使用 Spring 提供的 Spring Security oAuth2 搭建一套验证授权及资源访问服务的详细步骤,实现企业微服务架构时能够有效的控制多个服务的统一登录、授权及资源保护工作。
一、Oauth2
oAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。
二、Spring Security
Spring Security 是一个安全框架,前身是 Acegi Security,能够为 Spring 企业应用系统提供声明式的安全访问控制。Spring Security 基于 Servlet 过滤器、IoC 和 AOP,为 Web 请求和方法调用提供身份确认和授权处理,避免了代码耦合,减少了大量重复代码工作。
三、四种授权模式
3.1 简化模式(implicit)
适用于纯静态应用,
token
容易泄露,不安全,不推荐使用。
3.1.1 地址
【授权服务地址】/oauth/authorize?client_id=【客户端ID】&response_type=token
3.2 授权码模式(authorization code)
安全系数最高.授权码模式适用于有自己的服务器的应用,它是一个一次性的临时凭证,用来换取 access_token 和 refresh_token。
【授权服务器地址】/oauth/authorize?client_id=【客户端ID】&response_type=token
3.3 密码模式(resource owner password credentials)
密码模式中,用户向客户端提供自己的用户名和密码。客户端使用这些信息,向 “服务商提供商” 索要授权。在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分。
【授权服务器地址】/oauth/token?client_id=web_dev&client_secret=【客户端ID】&grant_type=password&username=【用户名】&password=【密码】
3.4 客户端模式(client credentials)
如果信任关系再进一步,或者调用者是一个后端的模块,没有用户界面的时候,可以使用客户端模式。鉴权服务器直接对客户端进行身份验证,验证通过后,返回 token。
【授权服务器地址】/oauth/token?client_id=【客户端Id】&client_secret=【客户端密码】&grant_type=client_credentials
四、搭建工程
4.1 父工程
新建一个
maven
工程,添加依赖如下。
4.1.2 xml
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.dingwen</groupId>
<artifactId>dingwen-auth</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<!--授权服务器-->
<module>auth-authorization-server</module>
<!--资源服务器-->
<module>auth-resource-server</module>
</modules>
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<!--始终从远程仓库获取,不试用本地仓-->
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring.cloud.version>Greenwich.SR1</spring.cloud.version>
<spring.cloud.starter.oauth2.version>2.1.2.RELEASE</spring.cloud.starter.oauth2.version>
<mybatis.plus.boot.starter.version>3.4.2</mybatis.plus.boot.starter.version>
<mysql.connector.java.version>8.0.15</mysql.connector.java.version>
<lombok.version>1.18.8</lombok.version>
<spring.boot.starter.test>2.1.5.RELEASE</spring.boot.starter.test>
<spring.boot.starter.web>2.1.5.RELEASE</spring.boot.starter.web>
</properties>
<dependencyManagement>
<dependencies>
<!-- springCloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--mybatis - plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis.plus.boot.starter.version}</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
<version>${lombok.version}</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.connector.java.version}</version>
</dependency>
<!--oauth2-->
<!--security-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
<version>${spring.cloud.starter.oauth2.version}</version>
</dependency>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring.boot.starter.web}</version>
</dependency>
<!--test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<version>${spring.boot.starter.test}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
4.1.2 项目结构
4.2 授权服务器
4.2.1 xml
<?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>
<groupId>com.dingwen</groupId>
<artifactId>dingwen-auth</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.dingwen.auause</groupId>
<artifactId>auth-authorization-server</artifactId>
<version>1.0</version>
<name>auth-authorization-server</name>
<description>授权服务器</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--mybatis - plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--oauth2-->
<!--security-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<developers>
<developer>
<id>auth</id>
<name>dingwen</name>
<email>dingwenemail@qq.com</email>
</developer>
</developers>
</project>
4.2.2 项目结构
4.2.3 数据库准备
sql文件在工程的doc目录下,建表语句中有详细的每张表的字段含义。
4.2.4 授权服务器配置
package com.dingwen.auause.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider;
import javax.sql.DataSource;
/**
* 配置认证服务器
*
* @author dingwen
* 2021.05.12 14:37
*/
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
private static final String CLIENT_ID = "web_dev";
private static final String SECRET = "dingwen_web";
private static final String AUTHORIZED_GRANT_TYPES = "authorization_code";
private static final String SCOPES = "write";
private static final String REDIRECT_URIS = "http:///www.baidu.com";
private final BCryptPasswordEncoder bCryptPasswordEncoder;
private final DataSource dataSource;
private final AuthenticationManager authenticationManager;
private final UserDetailsService userDetailsService;
@Autowired
AuthorizationServerConfiguration(BCryptPasswordEncoder bCryptPasswordEncoder,
DataSource dataSource,
AuthenticationManager authenticationManager,
UserDetailsService userDetailsService
) {
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
this.dataSource = dataSource;
this.authenticationManager = authenticationManager;
this.userDetailsService = userDetailsService;
}
/*
* 配置 TokenStore
* @return TokenStore
*/
@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore10分钟,教你快速搭建一套属于自己的分布式文件系统