Spring安全和角度

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring安全和角度相关的知识,希望对你有一定的参考价值。

Spring安全和角度(二)_身份验证

使用 OAuth2 进行单点登录

在本节中,我们继续我们的讨论如何使用弹簧安全跟角在“单页应用程序”中。在这里,我们展示如何使用春季安全密钥䋰春云将我们的 API 网关扩展到后端资源,以执行单点登录和 OAuth2 令牌身份验证。这是一系列部分中的第五部分,您可以通过阅读第一部分,或者您可以直接转到Github中的源代码.在最后一节我们构建了一个小型分布式应用程序,它使用春季会议对后端资源进行身份验证,以及春云在 UI 服务器中实现嵌入式 API 网关。在本节中,我们将身份验证责任提取到单独的服务器,以使我们的 UI 服务器成为授权服务器可能的许多单一登录应用程序中的第一个。这是当今许多应用程序中的常见模式,无论是在企业还是在社交初创公司中。我们将使用 OAuth2 服务器作为身份验证器,以便我们也可以使用它来为后端资源服务器授予令牌。Spring Cloud 会自动将访问令牌中继到我们的后端,并使我们能够进一步简化 UI 和资源服务器的实现。


提醒:如果您正在使用示例应用程序完成本节,请务必清除浏览器缓存中的 Cookie 和 HTTP 基本凭据。在Chrome中,为单个服务器执行此操作的最佳方法是打开一个新的隐身窗口。


创建 OAuth2 授权服务器

我们的第一步是创建一个新服务器来处理身份验证和令牌管理。按照中的步骤操作第一部分我们可以从Spring Boot Initializr.例如,在类似UN*X的系统上使用curl:

$ curl https://start.spring.io/starter.tgz -d dependencies=web,security -d name=authserver | tar -xzvf -

然后,您可以将该项目(默认情况下是普通的Maven Java项目)导入到您喜欢的IDE中,或者只是在命令行上处理文件和“mvn”。

添加 OAuth2 依赖项

我们需要添加春季OAuth依赖关系,所以在我们的聚 甲醛我们添加:

绒球.xml

<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>

授权服务器非常容易实现。最小版本如下所示:

身份验证服务器应用程序.java

@SpringBootApplication
@EnableAuthorizationServer
public class AuthserverApplication extends WebMvcConfigurerAdapter

public static void main(String[] args)
SpringApplication.run(AuthserverApplication.class, args);


我们只需要再做 1 件事(添加后):​​@EnableAuthorizationServer​

应用程序属性

---
...
security.oauth2.client.clientId: acme
security.oauth2.client.clientSecret: acmesecret
security.oauth2.client.authorized-grant-types: authorization_code,refresh_token,password
security.oauth2.client.scope: openid
---

这会使用机密和一些授权授权类型(包括“authorization_code”)注册客户端“acme”。

现在让我们让它在端口 9999 上运行,使用可预测的密码进行测试:

应用程序属性

server.port=9999
security.user.password=password
server.contextPath=/uaa
...

我们还设置了上下文路径,使其不使用默认值(“/”),否则您可能会将本地主机上其他服务器的cookie发送到错误的服务器。因此,让服务器运行,我们可以确保它正常工作:

$ mvn spring-boot:run

或在 IDE 中启动该方法。​​main()​

测试授权服务器

我们的服务器正在使用 Spring Boot 默认安全设置,所以就像服务器一样第一部分​它将受到 HTTP 基本身份验证的保护。启动授权代码令牌授予​您访问授权端点,例如​​http://localhost:9999/uaa/oauth/authorize?response_type=code&client_id=acme&redirect_uri=http://example.com​​身份验证后,您将获得一个重定向到带有授权代码的 example.com,例如http://example.com/?code=jYWioI.

出于此示例应用程序的目的,我们创建了一个没有注册重定向的客户端“Acme”,这使我们能够获得 example.com 的重定向。在生产应用程序中,应始终注册重定向(并使用 HTTPS)。

可以使用令牌终结点上的“acme”客户端凭据将代码交换为访问令牌:

$ curl acme:acmesecret@localhost:9999/uaa/oauth/token  \\
-d grant_type=authorization_code -d client_id=acme \\
-d redirect_uri=http://example.com -d code=jYWioI
"access_token":"2219199c-966e-4466-8b7e-12bb9038c9bb","token_type":"bearer","refresh_token":"d193caf4-5643-4988-9a4a-1c03c9d657aa","expires_in":43199,"scope":"openid"

访问令牌是 UUID (“2219199c...”),由服务器中的内存中令牌存储提供支持。我们还获得了一个刷新令牌,当当前访问令牌过期时,我们可以使用该令牌获取新的访问令牌。

由于我们允许为“Acme”客户端授予“密码”,因此我们还可以使用 curl 和用户凭据而不是授权代码直接从令牌端点获取令牌。这不适合基于浏览器的客户端,但对于测试很有用。

如果您点击上面的链接,您将看到Spring OAuth提供的白标UI。首先,我们将使用它,我们可以稍后回来加强它,就像我们在第二部分对于自包含服务器。

更改资源服务器

如果我们继续第四部分,我们的资源服务器正在使用春季会议用于身份验证,因此我们可以将其取出并替换为Spring OAuth。我们还需要删除 Spring 会话和 Redis 依赖项,因此将其替换为:

绒球.xml

<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
</dependency>

有了这个:

绒球.xml

<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>

,然后从​​Filter​​主要应用类,将其替换为方便的注释(来自 Spring Security OAuth2):​​@EnableResourceServer​

资源应用.java

@SpringBootApplication
@RestController
@EnableResourceServer
class ResourceApplication

@RequestMapping("/")
public Message home()
return new Message("Hello World");


public static void main(String[] args)
SpringApplication.run(ResourceApplication.class, args);

通过这一更改,应用程序已准备好挑战访问令牌而不是HTTP Basic,但我们需要配置更改才能实际完成该过程。我们将添加少量外部配置(在“application.properties”中),以允许资源服务器解码给定的令牌并对用户进行身份验证:

应用程序属性

...
security.oauth2.resource.userInfoUri: http://localhost:9999/uaa/user

这告诉服务器它可以使用令牌访问“/user”终结点并使用它来派生身份验证信息(这有点类似于​​“/me”终结点​​在脸书 API 中)。实际上,它为资源服务器提供了一种解码令牌的方法,如Spring OAuth2中的接口所示。​​ResourceServerTokenServices​

运行应用程序并使用命令行客户端访问主页:

$ curl -v localhost:9000
> GET / HTTP/1.1
> User-Agent: curl/7.35.0
> Host: localhost:9000
> Accept: */*
>
< HTTP/1.1 401 Unauthorized
...
< WWW-Authenticate: Bearer realm="null", error="unauthorized", error_description="An Authentication object was not found in the SecurityContext"
< Content-Type: application/json;charset=UTF-8
"error":"unauthorized","error_description":"An Authentication object was not found in the SecurityContext"

您将看到一个带有“WWW-Authenticate”标头的 401,指示它需要持有者令牌。

到目前为止,这不是将资源服务器与解码令牌的方式连接起来的唯一方法。事实上,这是一个最低的共同点(不是规范的一部分),但通常可以从OAuth2提供商(如Facebook,Cloud Foundry,Github)获得,并且可以使用其他选择。例如,您可以在令牌本身中对用户身份验证进行编码(例如,使用​​userInfoUri​​智威汤逊​),或使用共享后端存储。CloudFoundry中还有一个端点,它提供比用户信息端点更详细的信息,但需要更彻底的身份验证。不同的选项(自然)提供了不同的好处和权衡,但对这些选项的全面讨论超出了本节的范围。​​/token_info​

实现用户终端节点

在授权服务器上,我们可以轻松添加该端点

身份验证服务器应用程序.java

@SpringBootApplication
@RestController
@EnableAuthorizationServer
@EnableResourceServer
public class AuthserverApplication

@RequestMapping("/user")
public Principal user(Principal user)
return user;


...

我们添加了一个与 UI 服务器相同的​​@RequestMapping​​第二部分,以及来自 Spring OAuth 的注释,默认情况下,它保护授权服务器中除“/oauth/*”端点之外的所有内容。​​@EnableResourceServer​

有了该端点,我们可以测试它和问候语资源,因为它们现在都接受由授权服务器创建的持有者令牌:

$ TOKEN=2219199c-966e-4466-8b7e-12bb9038c9bb
$ curl -H "Authorization: Bearer $TOKEN" localhost:9000
"id":"03af8be3-2fc3-4d75-acf7-c484d9cf32b1","content":"Hello World"
$ curl -H "Authorization: Bearer $TOKEN" localhost:9999/uaa/user
"details":...,"principal":"username":"user",...,"name":"user"

(替换您从自己的授权服务器获取的访问令牌的值,以使其自己工作)。

用户界面服务器

我们需要完成的这个应用程序的最后一部分是 UI 服务器,提取身份验证部分并委派给授权服务器。所以,就像资源服务器,我们首先需要删除 Spring 会话和 Redis 依赖项,并将它们替换为 Spring OAuth2。因为我们在 UI 层中使用 Zuul,所以我们实际使用而不是直接使用(这设置了一些自动配置以通过代理中继令牌)。​​spring-cloud-starter-oauth2​​​​spring-security-oauth2​

完成后,我们还可以删除会话过滤器和“/user”端点,并将应用程序设置为重定向到授权服务器(使用注释):​​@EnableOAuth2Sso​

Ui应用程序.java

@SpringBootApplication
@EnableZuulProxy
@EnableOAuth2Sso
public class UiApplication

public static void main(String[] args)
SpringApplication.run(UiApplication.class, args);


...

召回自第四部分UI 服务器凭借 ,充当 API 网关,我们可以在 YAML 中声明路由映射。因此,可以将“/user”端点代理到授权服务器:​​@EnableZuulProxy​

应用程序.yml

zuul:
routes:
resource:
path: /resource/**
url: http://localhost:9000
user:
path: /user/**
url: http://localhost:9999/uaa/user

最后,我们需要将应用程序更改为 a,因为现在它将用于修改由以下设置的 SSO 筛选器链中的默认值:​​WebSecurityConfigurerAdapter​​​​@EnableOAuth2Sso​

安全配置.java

@SpringBootApplication
@EnableZuulProxy
@EnableOAuth2Sso
public class UiApplication extends WebSecurityConfigurerAdapter
@Override
public void configure(HttpSecurity http) throws Exception
http
.logout().logoutSuccessUrl("/").and()
.authorizeRequests().antMatchers("/index.html", "/app.html", "/")
.permitAll().anyRequest().authenticated().and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());


主要更改(除了基类名称之外)是匹配器进入自己的方法,不再需要任何方法。显式配置显式添加不受保护的成功 URL,以便成功返回 XHR 请求。​​formLogin()​​​​logout()​​​​/logout​

注释还有一些必需的外部配置属性,以便能够与正确的授权服务器联系并进行身份验证。所以我们在 :​​@EnableOAuth2Sso​​​​application.yml​

应用程序.yml

security:
...
oauth2:
client:
accessTokenUri: http://localhost:9999/uaa/oauth/token
userAuthorizationUri: http://localhost:9999/uaa/oauth/authorize
clientId: acme
clientSecret: acmesecret
resource:
userInfoUri: http://localhost:9999/uaa/user

其中大部分是关于OAuth2客户端(“acme”)和授权服务器位置。还有一个(就像在资源服务器中一样),以便用户可以在 UI 应用本身中进行身份验证。​​userInfoUri​

如果希望 UI 应用程序能够自动刷新过期的访问令牌,则必须将令牌注入执行中继的 Zuul 筛选器中。您可以通过创建该类型的 bean 来执行此操作(有关详细信息,请查看):​​OAuth2RestOperations​​​​OAuth2TokenRelayFilter​

@Bean
protected OAuth2RestTemplate OAuth2RestTemplate(
OAuth2ProtectedResourceDetails resource, OAuth2ClientContext context)
return new OAuth2RestTemplate(resource, context);

在客户端中

我们仍然需要对前端的 UI 应用程序进行一些调整以触发到授权服务器的重定向。在这个简单的演示中,我们可以将 Angular 应用程序简化为最基本的内容,以便您可以更清楚地看到正在发生的事情。因此,我们暂时放弃使用表单或路线,回到单个 Angular 组件:

app.component.ts

import  Component  from @angular/core;
import HttpClient from @angular/common/http;
import rxjs/add/operator/finally;

@Component(
selector: app-root,
templateUrl: ./app.component.html,
styleUrls: [./app.component.css]
)
export class AppComponent

title = Demo;
authenticated = false;
greeting = ;

constructor(private http: HttpClient)
this.authenticate();


authenticate()

this.http.get(user).subscribe(response =>
if (response[name])
this.authenticated = true;
this.http.get(resource).subscribe(data => this.greeting = data);
else
this.authenticated = false;

, () => this.authenticated = false; );


logout()
this.http.post(logout, ).finally(() =>
this.authenticated = false;
).subscribe();


处理所有内容,获取用户详细信息,如果成功,则发送问候语。它还提供该功能。​​AppComponent​​​​logout​

现在我们需要为这个新组件创建模板:

app.component.html

<div class="container">
<ul class="nav nav-pills">
<li><a>Home</a></li>
<li><a href="login">Login</a></li>
<li><a (click)="logout()">Logout</a></li>
</ul>
</div>
<div class="container">
<h1>Greeting</h1>
<div [hidden]="!authenticated">
<p>The ID is greeting.id</p>
<p>The content is greeting.content</p>
</div>
<div [hidden]="authenticated">
<p>Login to see your greeting</p>
</div>

并将其作为 包含在主页中。​​<app-root/>​

请注意,“登录”的导航链接是带有(不是角度路由)的常规链接。它转到的“/login”端点由 Spring Security 处理,如果用户未经身份验证,则会导致重定向到授权服务器。​​href​

它是如何工作的?

现在一起运行所有服务器,并在浏览器中访问 UI​​http://localhost:8080​​.单击“登录”链接,您将被重定向到授权服务器进行身份验证(HTTP Basic弹出窗口)并批准令牌授予(白标HTML),然后重定向到UI中的主页,并使用与我们对UI进行身份验证相同的令牌从OAuth2资源服务器获取问候语。

如果您使用某些开发人员工具,则可以在浏览器中看到浏览器和后端之间的交互(通常 F12 会打开它,默认情况下在 Chrome 中工作,可能需要 Firefox 中的插件)。以下是摘要:

动词

路径

地位

响应

获取

/

200

索引.html

获取

/*。.js

200

来自角度的资产

获取

/用户

302

重定向至登录页面

获取

/登录

302

重定向至“身份验证服务器”诊断树

获取

(UAA)/OAuth/authorize

401

(忽略)

获取

/登录

302

重定向至“身份验证服务器”诊断树

获取

(UAA)/OAuth/authorize

200

HTTP 基本身份验证发生在这里

发布

(UAA)/OAuth/authorize

302

用户批准授权,重定向至/登录

获取

/登录

302

重定向至主页

获取

/用户

200

(代理)经过 JSON 身份验证的用户

获取

/应用.html

200

主页的 HTML 部分

获取

/资源

200

(代理)JSON问候语

前缀为 (uaa) 的请求是发往授权服务器的请求。标记为“忽略”的响应是 Angular 在 XHR 调用中收到的响应,由于我们不处理这些数据,因此它们被丢弃在地板上。对于“/user”资源,我们确实会查找经过身份验证的用户,但由于它在第一次调用中不存在,因此该响应将被丢弃。

在 UI 的“/trace”端点(向下滚动到底部)中,您将看到对“/user”和“/resource”的代理后端请求,以及持有者令牌而不是 cookie(因为它本来会在​​remote:true​​第四部分) 用于身份验证。Spring Cloud Security已经为我们解决了这个问题:通过认识到我们已经并且已经发现(默认情况下)我们希望将令牌中继到代理后端。​​@EnableOAuth2Sso​​​​@EnableZuulProxy​

与前面的部分一样,尝试为“/trace”使用不同的浏览器,这样就不会有身份验证交叉的机会(例如,如果您使用 Chrome 测试用户界面,请使用 Firefox)。

注销体验

如果单击“注销”链接,您将看到主页已更改(不再显示问候语),因此用户不再通过UI服务器进行身份验证。单击“登录”,您实际上不需要返回授权服务器中的身份验证和批准周期(因为您尚未注销)。关于这是否是理想的用户体验,意见分歧,这是一个众所周知的棘手问题(单点注销:科学直销文章和希伯勒斯文档​).理想的用户体验在技术上可能不可行,有时您还必须怀疑用户是否真的想要他们所说的东西。“我想注销将我注销”听起来很简单,但明显的回应是,“注销了什么?您想注销此 SSO 服务器控制的所有系统,还是仅注销您单击“注销”链接的系统?如果您有兴趣,那么有后面的部分本教程将更深入地讨论它。

结论

这几乎是我们通过Spring Security和Angular堆栈的浅层之旅的结束。我们现在有一个很好的架构,在三个独立的组件中明确了职责,即 UI/API 网关、资源服务器和授权服务器/令牌授予者。现在,所有层中的非业务代码量都很少,并且很容易看出在哪里扩展和改进了具有更多业务逻辑的实现。接下来的步骤将是整理授权服务器中的UI,并可能添加更多测试,包括javascript客户端上的测试。另一个有趣的任务是提取所有样板代码并将其放入一个库中(例如“spring-security-angular”),其中包含Spring Security和Spring Session自动配置以及Angular部分中导航控制器的一些webjars资源。阅读了 thir 系列中的部分后,任何希望了解 Angular 或 Spring Security 内部工作原理的人都可能会感到失望,但如果您想了解它们如何很好地协同工作以及一点点配置如何走很长的路,那么希望您能有一个很好的体验。春云是新的,这些示例在编写时需要快照,但有可用的候选版本和即将推出的 GA 版本,因此请查看并发送一些反馈通过 Github或gitter.im.

这下一节在本系列中是关于访问决策(身份验证之外),并在同一代理后面使用多个 UI 应用程序。

附录:授权服务器的引导 UI 和 JWT 令牌

您将在Github中的源代码它有一个漂亮的登录页面和用户批准页面,其实现方式类似于我们在登录页面中执行的方式第二部分.它还使用智威汤逊对令牌进行编码,因此资源服务器可以从令牌本身中提取足够的信息来执行简单的身份验证,而不是使用“/user”终结点。浏览器客户端仍然使用它,通过 UI 服务器代理,以便它可以确定用户是否经过身份验证(与实际应用程序中对资源服务器的可能调用次数相比,它不需要经常这样做)。

多个 UI 应用程序和一个网关

在本节中,我们继续我们的讨论如何使用弹簧安全跟角在“单页应用程序”中。在这里,我们展示如何使用春季会议䋰春云结合我们在第二部分和第四部分中构建的系统的功能,实际上最终构建了 3 个具有不同职责的单页应用程序。目的是建立一个网关(如第四部分),不仅用于 API 资源,还用于从后端服务器加载 UI。我们简化了令牌整理位第二部分通过使用网关将身份验证传递到后端。然后,我们扩展系统以展示如何在后端做出本地、精细的访问决策,同时仍然控制网关的身份和身份验证。对于构建分布式系统来说,这是一个非常强大的模型,并且在我们构建的代码中引入功能时,我们可以探索许多好处。


提醒:如果您正在使用示例应用程序完成本节,请务必清除浏览器缓存中的 Cookie 和 HTTP 基本凭据。在Chrome中,最好的方法是打开一个新的隐身窗口。


目标体系结构

以下是我们将要开始构建的基本系统的图片:

Spring安全和角度(二)_应用程序_02

与本系列中的其他示例应用程序一样,它有一个 UI(HTML 和 JavaScript)和一个资源服务器。喜欢中的示例第四节它有一个网关,但在这里它是独立的,不是 UI 的一部分。UI 有效地成为后端的一部分,为我们提供了更多选择来重新配置和重新实现功能,并带来了我们将看到的其他好处。

浏览器会转到网关以获取所有内容,并且不必了解后端的体系结构(从根本上说,它不知道有后端)。浏览器在此网关中执行的操作之一是身份验证,例如,它发送用户名和密码,例如第二节,它会得到一个饼干作为回报。在后续请求中,它会自动提供 cookie,网关将其传递到后端。无需在客户端上编写代码即可启用 cookie 传递。后端使用 cookie 进行身份验证,并且由于所有组件共享一个会话,因此它们共享有关用户的相同信息。与此形成对比第五节其中 cookie 必须转换为网关中的访问令牌,然后访问令牌必须由所有后端组件独立解码。

如在第四节网关简化了客户端和服务器之间的交互,并提供了一个小的、定义明确的表面来处理安全性。例如,我们不需要担心跨源资源共享,这是一个受欢迎的缓解,因为它很容易出错。

我们将要构建的完整项目的源代码位于Github在这里,因此您可以根据需要克隆项目并直接从那里工作。此系统的最终状态中有一个额外的组件(“双管理员”),因此暂时忽略它。

构建后端

在此体系结构中,后端与“春季会议”我们内置的示例第三节,除了它实际上不需要登录页面。获得我们这里想要的内容的最简单方法可能是从第 III 节复制“资源”服务器并从“基本”样本在第一节.要从“基本”UI到我们在这里想要的UI,我们只需要添加几个依赖项(就像我们第一次使用时一样春季会议在第三节中):

绒球.xml

<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
</dependency>

由于这现在是一个 UI,因此不需要“/resource”终结点。完成此操作后,您将拥有一个非常简单的 Angular 应用程序(与“基本”示例中相同),它大大简化了对其行为的测试和推理。

最后,我们希望这个服务器作为后端运行,所以我们将给它一个非默认端口来侦听(在):​​application.properties​

应用程序属性

server.port: 8081
security.sessions: NEVER

如果这是全部内容,那么应用程序将是安全的,并且名为“user”的用户可以使用随机密码访问,但在启动时打印在控制台上(在日志级别 INFO)。“security.sessions”设置意味着Spring Security将接受cookie作为身份验证令牌,但除非它们已经存在,否则不会创建它们。​​application.properties​

资源服务器

资源服务器很容易从我们现有的一个示例生成。它与 中的“春季会话”资源服务器相同第三节:只是一个“/resource”端点 Spring 会话来获取分布式会话数据。我们希望此服务器具有要侦听的非默认端口,并且我们希望能够在会话中查找身份验证,因此我们需要这个(在):​​application.properties​

应用程序属性

server.port: 9000
security.sessions: NEVER

我们将发布对消息资源的更改,这是本教程中的新功能。这意味着我们将需要在后端进行CSRF保护,并且我们需要做通常的技巧来使Spring Security与Angular很好地配合使用:

@Override
protected void configure(HttpSecurity http) throws Exception
http.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());

完成的示例是在 GitHub 这里如果你想看一眼。

网关

对于网关的初始实现(最简单的方法),我们可以只使用一个空的 Spring Boot Web 应用程序并添加注释。正如我们在​​@EnableZuulProxy​​第一节有几种方法可以做到这一点,一种是使用Spring Initializr以生成框架项目。更容易的是使用春云初始化这是一回事,但对于春云应用。使用与第 I 节中相同的命令行操作顺序:

$ mkdir gateway && cd gateway
$ curl https://cloud-start.spring.io/starter.tgz -d style=web \\
-d style=security -d style=cloud-zuul -d name=gateway \\
-d style=redis | tar -xzvf -

然后,您可以将该项目(默认情况下是普通的Maven Java项目)导入到您喜欢的IDE中,或者只是在命令行上处理文件和“mvn”。有一个版本在 GitHub 中如果你想从那里开始,但它有一些我们还不需要的额外功能。

从空白的 Initializr 应用程序开始,我们添加 Spring 会话依赖项(如上面的 UI 所示)。网关已准备好运行,但它还不知道我们的后端服务,所以让我们在其中设置它(如果您执行了上面的 curl 操作,请重命名):​​application.yml​​​​application.properties​

应用程序.yml

zuul:
sensitive-headers:
routes:
ui:
url: http://localhost:8081
resource:
url: http://localhost:9000
security:
user:
password:
password
sessions: ALWAYS

代理中有 2 条路由,它们都使用该属性将 cookie 传递到下游,UI 和资源服务器各一条,并且我们设置了默认密码和会话持久性策略(告诉 Spring Security 始终在身份验证时创建会话)。最后一点很重要,因为我们希望在网关中管理身份验证,因此会话。​​sensitive-headers​

启动并运行

我们现在有三个组件,在 3 个端口上运行。如果将浏览器指向​​http://localhost:8080/ui/​​您应该会收到 HTTP 基本质询,并且可以作为“用户/密码”(您在网关中的凭据)进行身份验证,完成此操作后,您应该会在 UI 中看到一个问候语,通过通过代理对资源服务器的后端调用。

如果您使用某些开发人员工具,则可以在浏览器中看到浏览器和后端之间的交互(通常 F12 会打开它,默认情况下在 Chrome 中工作,可能需要 Firefox 中的插件)。以下是摘要:

动词

路径

地位

响应

获取

/用户界面/

401

浏览器提示进行身份验证

获取

/用户界面/

200

索引.html

获取

/ui/*.js

200

角度资产

获取

/ui/js/hello.js

200

应用程序逻辑

获取

/ui/user

200

认证

获取

/资源/

200

JSON问候语

您可能看不到 401,因为浏览器将主页加载视为单个交互。所有请求都是代理的(网关中尚无内容,超出执行器端点进行管理)。

万岁,它有效!您有两个后端服务器,其中一个是 UI,每个服务器都具有独立的功能,可以单独测试,并且它们与您控制的安全网关连接在一起,并且您已为其配置了身份验证。如果浏览器无法访问后端,那也没关系(事实上,这可能是一个优势,因为它可以让您更好地控制物理

以上是关于Spring安全和角度的主要内容,如果未能解决你的问题,请参考以下文章

Spring安全和角度

尝试某些请求时出现Spring安全性和角度401错误

带有spring-boot安全休息api的角度2

9 月安全事件回顾

Spring Security

我应该使用基于 Spring 安全角色的授权还是 Angular Route Guards 或两者兼而有之? [关闭]