当前位置: 首页>編程日記>正文

OAuth2资源服务器

OAuth2资源服务器

OAuth2资源服务器

  • 1 说明
  • 2 资源服务器实现
    • 2.1 创建工程
    • 2.2 资源服务器配置类
    • 2.3 用户资源请求入口类
    • 2.4 用户资源获取服务接口
    • 2.5 用户资源获取服务实现类
    • 2.6 主启动类
    • 2.7 其它配置
  • 3 测试
    • 3.1 获取令牌
    • 3.2 请求资源
  • 4 总结

1 说明

授权服务器主要是提供用户认证、授权、颁发令牌等功能,而资源服务器主要是保护用户资源。授权服务器先给合法的用户颁发令牌,用户再使用获得的令牌到资源服务器申请受保护的用户资源,而资源服务器接收到用户的请求后,会先验证用户的令牌,只有令牌合法才会把用户请求的资源返回给用户,否则拒绝返回。

资源服务器验证用户的令牌可以有多种方式,既可以把用户的令牌拿到授权服务器处进行验证,也可以自己验证。只有授权服务器使用非对称加密令牌或者使用对称加密令牌的方式,且资源服务器知道授权服务器用于加密令牌的密钥所对应的公钥时,资源服务器才能自己验证令牌。本示例中,授权服务器使用对称加密令牌的方式加密令牌,资源服务器自己验证令牌。

OAuth2授权服务器和四种授权方式这篇文章介绍了授权服务器以及基于授权码授权、密码授权、简化授权、客户端授权等四种授权方式的实现,因此,本文不再重复介绍授权服务器相关的内容,而主要是介绍资源服务器的实现。本文的资源服务器使用方法级的权限控制来保护用户资源。

2 资源服务器实现

本文主要是介绍资源服务器的实现,所以省略了授权服务器工程,同时也省略了eureka服务注册中心工程和common-model公共实体类工程。

2.1 创建工程

创建一个名为user-resource-server的spring cloud微服务工程(用户信息资源服务器),项目结构如下图所示:
在这里插入图片描述
版本说明:

  • Spring boot: 2.1.3
  • Spring Cloud: Greenwich.SR1
  • jdk: 1.8

2.2 资源服务器配置类

要想启用资源服务器,需要实现一个继承了ResourceServerConfigurerAdapter类的配置类,并且在实现的配置类中使用@EnableResourceServer注解。本文的资源服务器配置类AuthorizationServerConfig代码如下所示:

package com.user.resource.server.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;/*** OAuth的资源服务器配置* 注意:必须继承ResourceServerConfigurerAdapter类,并使用@Configuration和@EnableResourceServer注解*/
@Configuration
@EnableResourceServer
public class ResourceServerConfig  extends ResourceServerConfigurerAdapter {/*** 微服务的Http安全配置*/@Overridepublic void configure(HttpSecurity http) throws Exception {/*** 不允许跨域请求,/getQQUserAuth请求不需要认证,其它请求都需要认证*/http.csrf().disable().authorizeRequests().antMatchers("/getQQUserAuth").permitAll().anyRequest().authenticated();}/*** 资源服务器的安全配置*/@Overridepublic void configure(ResourceServerSecurityConfigurer resources) throws Exception {/*** 设置令牌的存储方式*/resources.tokenStore(tokenStore());}/*** 创建令牌存储对象*/@Beanpublic TokenStore tokenStore() {/*** 使用JwtTokenStore时,必须注入一个JwtAccessTokenConverter,用于解析JWT令牌*/return new JwtTokenStore(jwtAccessTokenConverter());}/*** 创建JWT令牌转换器*/@Beanpublic JwtAccessTokenConverter jwtAccessTokenConverter(){/*** 设置JWT令牌的签名key*/JwtAccessTokenConverter converter = new JwtAccessTokenConverter();converter.setSigningKey("signingKey");return converter;}}

资源服务器配置类中主要是设置安全配置,以及设置令牌存储和验证的配置。

2.3 用户资源请求入口类

获取用户认证信息的接口不需要授杼就可以直接访问,获取用户详细信息的接口需要授权才能访问,而且只允许授权用户查询自己的详细信息。

package com.user.resource.server.controller;import com.common.model.domain.QQUser;
import com.common.model.ext.QQUserAuth;
import com.common.model.request.QQUserQuery;
import com.common.model.response.ResponseResult;
import com.user.resource.server.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;/*** 获取用户信息接口入口*/
@RestController
public class UserController {@AutowiredUserService userService;/*** 根据用户名获取认证用户信息(不要求用户已认证,即不要求有访问令牌)*/@PostMapping("/getQQUserAuth")public ResponseResult getQQUserAuth(@RequestBody QQUserQuery query) {QQUserAuth user = null;if(query == null) {return ResponseResult.getFailureResult("300", "没有接收到用户信息");} else if(!StringUtils.isEmpty(query.getUsername())) {user = userService.getQQUserAuthByUsername(query.getUsername());}if(user == null) {return ResponseResult.getFailureResult("300", "没有查询到该用户信息");} else {return ResponseResult.getSuccessResult().put("QQUserAuth", user);}}/*** 已认证用户查询自己的用户信息,不允许查询他人的用户信息(要求用户已认证,即要求有合法的访问令牌)*/@PostMapping("/api/getQQUser")@PreAuthorize("principal.equals(#query.getUsername())")public ResponseResult getQQUser(@RequestBody QQUserQuery query) {QQUser user = null;if(query == null) {return ResponseResult.getFailureResult("300", "没有接收到用户信息");} else if(!StringUtils.isEmpty(query.getUsername())) {user = userService.getQQUserByUsername(query.getUsername());}if(user == null) {return ResponseResult.getFailureResult("300", "没有获取到该用户信息");} else {return ResponseResult.getSuccessResult().put(user);}}}

2.4 用户资源获取服务接口

package com.user.resource.server.service;import com.common.model.domain.QQUser;
import com.common.model.ext.QQUserAuth;/*** 获取用户信息接口*/
public interface UserService {/*** 根据用户名获取认证用户信息*/QQUserAuth getQQUserAuthByUsername(String username);/*** 根据用户名获取用户详细信息*/QQUser getQQUserByUsername(String username);}

2.5 用户资源获取服务实现类

package com.user.resource.server.service.impl;import com.common.model.domain.QQUser;
import com.common.model.ext.QQUserAuth;
import com.user.resource.server.service.UserService;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;/*** 获取用户信息接口实现类*/
@Service
public class UserServiceImpl implements UserService {/*** 根据用户名获取认证用户信息*/@Overridepublic QQUserAuth getQQUserAuthByUsername(String username) {if (username.equals("admin")) {QQUserAuth user = new QQUserAuth();user.setId(1L);user.setUsername(username);/*** 密码为123(通过BCryptPasswordEncoderl加密后的密文)*/user.setPassword("$2a$10$U6g06YmMfRJXcNfLP28TR.xy21u1A5kIeY/OZMKBDVMbn7PGJiaZS");List<String> roles = new ArrayList<>();roles.add("ROLE_USER");user.setRoles(roles);return user;} else if (username.equals("employee")) {QQUserAuth user = new QQUserAuth();user.setId(2L);user.setUsername(username);/*** 密码为123(通过BCryptPasswordEncoderl加密后的密文)*/user.setPassword("$2a$10$U6g06YmMfRJXcNfLP28TR.xy21u1A5kIeY/OZMKBDVMbn7PGJiaZS");List<String> roles = new ArrayList<>();roles.add("ROLE_EMPLOYEE");user.setRoles(roles);return user;}return null;}/*** 根据用户名获取用户详细信息*/@Overridepublic QQUser getQQUserByUsername(String username) {if (username.equals("admin")) {QQUser user = new QQUser();user.setId(1L);user.setUsername(username);/*** 密码为123(通过BCryptPasswordEncoderl加密后的密文)*/user.setPassword("$2a$10$U6g06YmMfRJXcNfLP28TR.xy21u1A5kIeY/OZMKBDVMbn7PGJiaZS");user.setNickname("管理员");user.setName("张三");user.setGender(true);user.setCity("China");user.setCity("WuHan");user.setMobile("17371580000");user.setEmail("3612450000@qq.com");return user;} else if (username.equals("employee")) {QQUser user = new QQUser();user.setId(2L);user.setUsername(username);/*** 密码为123(通过BCryptPasswordEncoderl加密后的密文)*/user.setPassword("$2a$10$U6g06YmMfRJXcNfLP28TR.xy21u1A5kIeY/OZMKBDVMbn7PGJiaZS");user.setNickname("普通员工");user.setName("李四");user.setGender(true);user.setCity("China");user.setCity("WuHan");user.setMobile("17371580000");user.setEmail("3612450000@qq.com");return user;}return null;}}

2.6 主启动类

package com.user.resource.server;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.ComponentScan;/*** 用户信息资源服务器微服务启动类*/
@ComponentScan("com.user.resource.server.*")
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableEurekaClient
@SpringBootApplication
public class UserResourceServerApplication {public static void main(String[] args) {SpringApplication.run(UserResourceServerApplication.class, args);}}

2.7 其它配置

pom.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.resource.server</groupId><artifactId>user-resource-server</artifactId><version>0.0.1-SNAPSHOT</version><name>user-resource-server</name><description>用户资源服务</description><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.3.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><properties><java.version>1.8</java.version><spring-cloud.version>Greenwich.SR1</spring-cloud.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-security</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-oauth2</artifactId></dependency><dependency><groupId>com.common.model</groupId><artifactId>common-model</artifactId><version>0.0.1-SNAPSHOT</version></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

application.yml配置文件如下所示:

server:port: 15000spring:application:name: @pom.artifactId@eureka:client:serviceUrl:defaultZone: http://localhost:10000/eureka/instance:prefer-ip-address: trueinstance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${server.port}

3 测试

分别启动Eureka服务注册中心工程、auth-server授权服务器工程、user-resource-server用户资源服务器工程。

要想从用户资源服务器中获取受保护的用户资源(本文中是指用户的详细信息),需要先到授权服务器处进行认证、授权并获得访问令牌,然后才能使用访问令牌到用户资源服务器处请求受保护的用户资源。

3.1 获取令牌

从授权服务器获取令牌的方法请见OAuth2授权服务器和四种授权方式这篇文章。

本文使用用户名admin和密码123进行认证和授权,并基于密码授权方式获取令牌。获取的令牌如下图所示:
在这里插入图片描述

3.2 请求资源

本文中用户的详细信息属于受保护的用户资源,用户想要获取该资源,就必须要求用户已认证(即有合法的访问令牌),而且,本文中对获取用户详细信息这个方法设置了权限,只允许认证用户查询自己的用户详细信息。因此,本文从三个方面来测试:

  1. 用户在未授权(不带访问令牌)的情况下获取某个用户的详细信息。
  2. 用户在已授权(带访问令牌)的情况下获取自己的详细信息。
  3. 用户在已授权(带访问令牌)的情况下获取他人的详细信息。

使用访问令牌(access_token)到资源服务器请求受保护的用户资源时,需要以Bearer Token类型的认证头的方式把访问令牌添加到请求中。

1. 使用postman工具来发送请求,首先在不添加访问令牌的情况下直接查询admin用户的详细信息,请求详情如下所示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
请求结果如下图所示,提示该请求因为没有授权(即访问令牌)而被拒绝访问:
在这里插入图片描述

2. 使用postman工具来发送请求,在添加访问令牌的情况下查询admin用户的详细信息,请求详情如下所示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
请求结果如下图所示,成功的从资源服务器中admin用户的详细信息:
在这里插入图片描述
3. 使用postman工具来发送请求,在添加访问令牌的情况下查询employee用户的详细信息,请求详情如下所示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
请求结果如下图所示,提示该请求因为权限而被拒绝访问:
在这里插入图片描述
通过上面的三次测试,说明用户资源服务器确实起到了保护用户资源的作用,只有用户有合法的访问令牌时才允许用户获取受保护的用户资源。

4 总结

本文简要的介绍了资源服务器的实现方法和使用方法,但是实现的资源服务器还十分基础。关于授权服务器、用户认证、权限控制等相关的内容可以查阅以下几篇文章:

OAuth2授权服务器和四种授权方式 这篇文章介绍了授权服务器和四种授权方式的配置与使用方法。
Spring Security用户认证和权限控制(默认实现)这篇文章介绍了方法级别的权限控制。
Spring Security用户认证和权限控制(自定义实现)这篇文章介绍了URL级别的权限控制。

如果觉得本文对您有帮助,请关注博主的微信公众号,会经常分享一些Java和大数据方面的技术案例!
在这里插入图片描述


https://www.fengoutiyan.com/post/15420.html

相关文章:

  • oa手机端服务器地址
  • oauth20
  • 资源服务器
  • 手机oa服务器地址和端口
  • oauth21
  • 云服务器是
  • 购买云服务器
  • 腾讯云服务器
  • 鏡像模式如何設置在哪,圖片鏡像操作
  • 什么軟件可以把圖片鏡像翻轉,C#圖片處理 解決左右鏡像相反(旋轉圖片)
  • 手機照片鏡像翻轉,C#圖像鏡像
  • 視頻鏡像翻轉軟件,python圖片鏡像翻轉_python中鏡像實現方法
  • 什么軟件可以把圖片鏡像翻轉,利用PS實現圖片的鏡像處理
  • 照片鏡像翻轉app,java實現圖片鏡像翻轉
  • 什么軟件可以把圖片鏡像翻轉,python圖片鏡像翻轉_python圖像處理之鏡像實現方法
  • matlab下載,matlab如何鏡像處理圖片,matlab實現圖像鏡像
  • 圖片鏡像翻轉,MATLAB:鏡像圖片
  • 鏡像翻轉圖片的軟件,圖像處理:實現圖片鏡像(基于python)
  • canvas可畫,JavaScript - canvas - 鏡像圖片
  • 圖片鏡像翻轉,UGUI優化:使用鏡像圖片
  • Codeforces,CodeForces 1253C
  • MySQL下載安裝,Mysql ERROR: 1253 解決方法
  • 勝利大逃亡英雄逃亡方案,HDU - 1253 勝利大逃亡 BFS
  • 大一c語言期末考試試題及答案匯總,電大計算機C語言1253,1253《C語言程序設計》電大期末精彩試題及其問題詳解
  • lu求解線性方程組,P1253 [yLOI2018] 扶蘇的問題 (線段樹)
  • c語言程序設計基礎題庫,1253號C語言程序設計試題,2016年1月試卷號1253C語言程序設計A.pdf
  • 信奧賽一本通官網,【信奧賽一本通】1253:抓住那頭牛(詳細代碼)
  • c語言程序設計1253,1253c語言程序設計a(2010年1月)
  • 勝利大逃亡英雄逃亡方案,BFS——1253 勝利大逃亡
  • 直流電壓測量模塊,IM1253B交直流電能計量模塊(艾銳達光電)
  • c語言程序設計第三版課后答案,【渝粵題庫】國家開放大學2021春1253C語言程序設計答案
  • 18轉換為二進制,1253. 將數字轉換為16進制
  • light-emitting diode,LightOJ-1253 Misere Nim
  • masterroyale魔改版,1253 Dungeon Master
  • codeformer官網中文版,codeforces.1253 B
  • c語言程序設計考研真題及答案,2020C語言程序設計1253,1253計算機科學與技術專業C語言程序設計A科目2020年09月國家開 放大學(中央廣播電視大學)
  • c語言程序設計基礎題庫,1253本科2016c語言程序設計試題,1253電大《C語言程序設計A》試題和答案200901
  • 肇事逃逸車輛無法聯系到車主怎么辦,1253尋找肇事司機