相关文章:
在前面我们使用最小化配置的方式搭建了自己的授权服务器,现在我们依旧用最小化的方式配置自己的资源服务器。
资源服务器负责scope的鉴权、authorities的鉴权、基于用户角色的鉴权等。
1、 新建一个Spring Boot项目,命名为spring-security-resource-server
2、引入pom.xml依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
其中与授权服务器依赖不同的是,资源服务器有spring boot版本,版本号会有spring boot进行管理,不需要显示声明。
1、配置application.yml 文件
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: http://localhost:9000
该配置用于指定授权服务器地址,资源服务器将从该地址获取JWT令牌,并根据JWT中的属性进一步自我配置,发现授权服务器的公钥、验证JWT令牌。
2、创建配置类
@EnableWebSecurity(debug = true)
public class ResoruceServerConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.mvcMatchers("/userinfo/**").hasAuthority("SCOPE_userinfo")
.and()
.oauth2ResourceServer()
.jwt();
return http.build();
}
}
.mvcMatchers("/userinfo/**").hasAuthority("SCOPE_userinfo")匹配/userinfo/**地址,允许访问范围是SCOPE_userinfo
oauth2ResourceServer()定义为资源服务器
jwt()使用JWT令牌
3、 创建一个资源接口
/userinfo/用来获取资源所有者基本信息
@Data
public class UserInfoRes {
private String username;
}
创建Rest接口
@RestController
public class UserInfoController {
@GetMapping("/userinfo")
public UserInfoRes getUserInfo() {
UserInfoRes userInfoRes = new UserInfoRes();
userInfoRes.setUsername("阿提说说");
return userInfoRes;
}
}
目前我们客户端的配置是这样的:
spring:
security:
oauth2:
client:
registration:
gitee:
client-id: gitee_clientId
client-secret: gitee_secret
authorization-grant-type: authorization_code
redirect-uri: '{baseUrl}/login/oauth2/code/{registrationId}'
client-name: Gitee
github:
client-id: github_clientId
client-secret: github_secret
# 自定义
customize:
client-id: testClientId
client-secret: testClientSecret
authorization-grant-type: authorization_code
redirect-uri: '{baseUrl}/login/oauth2/code/{registrationId}'
client-name: Customize
scope:
- userinfo
provider:
gitee:
authorization-uri: https://gitee.com/oauth/authorize
token-uri: https://gitee.com/oauth/token
user-info-uri: https://gitee.com/api/v5/user
user-name-attribute: name
# 自定义
customize:
authorization-uri: http://localhost:9000/oauth2/authorize
token-uri: http://localhost:9000/oauth2/token
user-info-uri: http://localhost:9000/userinfo
user-name-attribute: username
这里我们只需要修改customize部分的user-info-uri和 user-name-attribute
调整后配置如下,其他部分跟原来是一样的。
customize:
authorization-uri: http://localhost:9000/oauth2/authorize
token-uri: http://localhost:9000/oauth2/token
user-info-uri: http://localhost:8090/userinfo
user-name-attribute: username
❗ user-name-attribute的名字,必须在user-info-uri返回的属性名中存在
在如上三部分配置完成后,就可以体验了,启动spring-security-resource-server、spring-security-authorization-server、spring-security-oauth2-client
浏览器访问地址:http://127.0.0.1:8080/hello,在授权完成后,即跳转回并显示结果。

ResourceServer下能看到带着token的/userinfo请求日志。
************************************************************
Request received for GET '/userinfo':
org.apache.catalina.connector.RequestFacade@3418bfc9
servletPath:/userinfo
pathInfo:null
headers:
accept: application/json
authorization: Bearer eyJraWQiOiI5YjZjZWMzNi05ZDYyLTRkMWMtOWRiNi0wMWM1ODQzMDc1N2UiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c2VyIiwiYXVkIjoidGVzdENsaWVudElkIiwibmJmIjoxNjYwOTU1ODQyLCJzY29wZSI6WyJ1c2VyaW5mbyJdLCJpc3MiOiJodHRwOlwvXC9sb2NhbGhvc3Q6OTAwMCIsImV4cCI6MTY2MDk1NjE0MiwiaWF0IjoxNjYwOTU1ODQyfQ.gVWwwfzB-xNuWWUBpgGokIOy5xwV9Wkd05k3rqpk1h92b-TWENB4ZArEL--zpngSyE8iuml0vG3veCv647FDx_EY56ClM-UxH-3Wq0D2f3b6WTgFO5RpCCwRLCHahBlV5g9plr7hWYY5uX2cQ4MsC4-ltZSR6wga5LSLDB-bIK46ZmJ3DOaQFwTTCpWB4OgOuq1j59i9XkgDUc_I8WUsHB4eEDEbBJeOmdimDn5O1Ux6nDhPgLMLcpnrt3lHLmXDTk8Q7hX7YBynO2VBm6wkTeYP4a2rfinfhW-LtF1o3hm8QAY0hn1QKSEeWU5K5qiIOVeSJ5FqrYJ_VQPadT1qAQ
user-agent: Java/11
host: localhost:8090
connection: keep-alive
Security filter chain: [
DisableEncodeUrlFilter
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CsrfFilter
LogoutFilter
BearerTokenAuthenticationFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]
************************************************************
到此,我们通过自己搭建的授权服务器和资源服务器,完整体验了OAuth2流程,再来体会下第一篇文章中说明的交互流程。

在整个流程中,我们使用的是最严密的授权码模式,它将用户引导到授权服务器进行身份验证,授权服务器将发放的访问令牌传递给客户端,目前主流都是使用该模式,因此特别重要,要好好体会。

源代码地址:https://github.com/jujunchen/21Study
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
我正在尝试设置一个puppet节点,但rubygems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由rubygems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢
我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby1.9+ 关于ruby-主要:Objectwhenrun
最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru
在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo
我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin