如何使用Okta和模板将Auth添加到您的PWA中

本文最初发布在Okta开发人员博客上 感谢您支持使SitePoint成为可能的合作伙伴。

渐进式Web应用程序 (PWA)是Web开发平台上的最新技术,它们及时出现是为了解决一个日益严重的问题。 当发布新功能时,许多公司都在努力使组织中孤立的开发团队保持最新。 一些公司甚至试图确定开发Web应用程序移动应用程序的成本是否值得。 毫不奇怪,大多数公司都希望避免这种头痛。 PWA可以为公司提供移动应用程序所需的许多功能,而无需管理多个团队和代码库。

PWA在快速连接时表现出色,在离线或通过Wi-Fi联接时仍表现良好,而Wi-Fi的联接速度还不够快,无法称为Wi-Fi(有时称为“ Lie-Fi”)。 它是通过缓存和JavaScript“服务工作者”来实现的,JavaScript“服务工作者”拦截服务器调用并首先尝试从缓存中提供数据,然后在服务器最终响应时,它将缓存的数据替换为服务器中的“刷新”数据。

最近, Ionic团队发布了一个名为Stencil的新项目。 Stencil是一个生成符合标准的Web组件的编译器。 与大多数JavaScript框架不同,它不会向浏览器交付代码的“框架”。 它仅使用您编写的代码,并使用其编译器来创建普通组件。 您还可以将Stencil的编译器您喜欢的框架一起使用。 Stencil入门项目是使用Stencil的最简单方法,它产生的基本应用程序在Lighthouse的渐进式Web应用程序记分卡上的得分接近100%。

要开始使用Stencil构建PWA,请克隆启动程序应用程序并将其与GitHub远程服务器分离。

警告 :模板尚未发布1.0版(截至撰写本文时)。 因此请注意,如果继续,您将处于早期采用者的领域。 如果发现错误,请提交问题

设置入门应用程序

git clone https://github.com/ionic-team/stencil-starter.git first-stencil
cd first-stencil
git remote rm origin

然后,安装新的Stencil应用程序将需要的所有依赖项。

npm install

您可能会在fsevents周围的node-pre-gyp fsevents看到一些警告。 这里什么也看不到。 这只是为了解决一个讨厌的小npm错误

接下来,将Okta Auth SDK(通过CDN)添加到index.html页面的底部, index.html</body>标记之前。

<script src="https://ok1static.oktacdn.com/assets/js/sdk/okta-auth-js/1.8.0/okta-auth-js.min.js" type="text/javascript"></script>

虽然有Okta的Auth SDK的npm软件包,但Stencil很难对其进行编译。 总体而言,如果您仅使用CDN来包括它,那么它现在效果更好。

如果您像我一样,接下来要做的就是运行npm start并使用Lighthouse检查该站点。 如果这样做,您会注意到分数有点低。 特别是,它不会注册服务工作者,也不会在离线时返回200。 这是因为它是开发构建,通常,您不希望服务人员在开发中拦截服务器调用并返回缓存的数据。

为了确保您可以准确地描绘出使用Stencil开箱即用的PWA类型,请确保使用npm run build运行生产 npm run build 。 完成后,您将看到一个www文件夹,并且在该文件夹内,您将看到一个sw.js文件。 那是您的服务人员!

设置您的Okta应用程序

如果您尚未这样做,请创建一个永久性的开发者帐户

注册后,单击顶部菜单中的“ 应用程序 ”。 然后单击“ 添加应用程序”

应用列表屏幕

然后,您将进入应用程序创建向导。 选择“ 单页应用程序” ,然后单击底部的“ 下一步 ”。

创建应用程序屏幕SPA

在下一个屏幕上,您将看到单页应用程序模板提供的默认设置。 将应用程序的名称更改为更具描述性的名称,例如“ Stencil SPA”。 另外,将基本URI和登录重定向URI设置更改为使用端口3333,因为这是应用程序将在其中运行的地方。 其余的默认设置都可以。

应用程序设置屏幕

点击底部的完成

从列表中选择新创建的应用程序,然后单击“ 常规”选项卡以查看常规设置。

常规设置客户端ID

在底部,您会看到一个Client ID设置(很明显,您不会感到困惑)。 复制它以在您的Stencil应用程序中使用。 您还将需要您的Okta组织URL,您可以在仪表板页面的右上角找到该URL。 它可能看起来像“ https://dev-XXXXXX.oktapreview.com”。

添加身份验证组件

components文件夹中,添加一个名为app-auth的新文件夹。 这是您的登录页面组件所在的位置。 您可以随心所欲地调用它,我只是遵循此处的入门应用程序设置的命名约定。 我绝对建议您尽早决定命名惯例并坚持使用。

在新创建的app-auth文件夹中,创建两个文件: app-auth.cssapp-auth.tsx 。 首先创建app-auth.tsx文件的外壳。

import { Component } from '@stencil/core';

@Component({
  tag: 'app-auth',
  styleUrl: 'app-auth.css'
})
export class AppAuth {
  render() {
    return <div>Hello</div>;
  }
}

如果像我一样,您可能会想:“这是什么样的科学怪人框架?”

您会在AppAuth类声明(如Angular)上看到@Component装饰器,然后在底部像React一样看到render()方法。 对我来说,这就是模具的美。 它吸收了两个流行框架的一些最佳部分,并使用它们来编译可重用的组件!

添加登录表格

接下来,将JSX(我说对了)添加到新组件中。 将render()方法更改为:

render() {
  return (
    <form class="app-auth">
      <div class="form-item">
        <label>
          Username:
          <input type="text" name="username" autocomplete="username" />
        </label>
      </div>
      <div class="form-item">
        <label>
          Password:
          <input
            type="password"
            name="password"
            autocomplete="current-password"
          />
        </label>
      </div>
      <div class="form-actions">
        <button type="button" onClick={() => this.login()}>
          Login
        </button>
      </div>
    </form>
  );
}

这只是一个普通的JSX表单,但登录按钮的onClick事件当前已连接到不存在的功能。

添加登录方法的依赖项

在创建该函数之前,您需要设置OktaAuth JavaScript对象以调用Okta API进行身份验证。 您将对象添加到组件的状态,因此在类声明的正下方添加以下行:

@State() authClient: any;

您还必须导入@State()装饰器。 这用于与组件内部状态有关的值。 在第一个import语句中,将State添加到解构列表中。

import { Component, State } from '@stencil/core'

您还需要从表单本身获取用户名和密码值,因此像您刚创建的那样,在@State()下方的代码中添加@Element() ,其内容如下:

@State() authClient: any;
@Element() host: HTMLElement;

然后还将@Element()装饰器添加到导入,使其显示为:

import { Component, State, Element } from '@stencil/core';

login()函数需要做的最后一件事是访问路由器,因此,如果他们的身份验证成功,则可以将用户重定向到他们的个人资料页面。 您将需要一个class属性,因此请将其添加到@Element正下方。

@State() authClient: any;
@Element() host: HTMLElement;
@Prop() history: RouterHistory;

要导入它,请将@Prop()装饰器添加到@Prop()入中,然后从核心导入语句下方的@stencil/router导入RouterHistory@Prop装饰器用于定义可以传递到组件中的属性。 在这种情况下,它不是传递的值,但是如果需要的话也可以。 最后的导入部分应显示为:

import { Component, Prop, State, Element, Listen } from '@stencil/core';
import { RouterHistory } from '@stencil/router';

最后,要使用从CDN引入的OktaAuth JavaScript库,请在import语句下方为其添加一个声明。

declare const OktaAuth: any;

添加登录方法

现在,您包括了获得登录功能以通过Okta组织对用户进行身份验证所需的一切。 首先,在AppAuth类的构造函数中设置OktaAuth对象。 在RouterHistory对象的属性下面,添加:

constructor() {
  this.authClient = new OktaAuth({
    clientId: '{yourClientId}',
    url: 'https://{yourOktaDomain}.com',
    issuer: 'default'
  });
}

您可以从Okta应用程序的常规设置页面获取客户端ID。

您还需要Okta仪表板页面右上角的Okta组织URL。

Okta仪表板组织网址

现在,所有东西都为login()函数设置好了,因此接下来将创建它。 在render()方法上方,添加一个login()函数。

login() {
  let inputs = this.host.querySelectorAll('input');
  let user = {
    username: inputs[0].value,
    password: inputs[1].value
  };

  return this.authClient.signIn(user)
    .then(res => {
      if (res.status === 'SUCCESS') {
        return this.authClient.token
          .getWithoutPrompt({
            responseType: 'id_token',
            scopes: ['openid', 'profile', 'email'],
            sessionToken: res.sessionToken,
            redirectUri: 'http://localhost:3333'
          })
          .then(token => {
            localStorage.setItem(
              'okta_id_token',
              JSON.stringify(token)
            );
            this.history.push('/profile', {});
          });
      } else {
        throw `Unable to handle ${res.status} status code`;
      }
    })
    .fail(function(err) {
      console.error(err);
    });
}

由于实际上是组件的“实质”,所以我将带您逐步了解这里发生的情况。

首先,将所有输入都放入组件的form元素内。 然后,使用用户名和密码从其各自的输入中创建用户对象。

接下来, authClient对象用于与创建的用户对象一起调用signIn()方法。 它返回一个promise,因此您可以通过获取响应来处理then条件,并检查响应的状态是否为200。如果是,则调用authClient.tokengetWithoutPrompt()方法,该方法还返回一个getWithoutPrompt() 。 它需要一个responseType属性,该属性设置为id_token ,因为这就是您想从Okta获得的。 您还要求提供三个范围,这些范围将为您提供与新身份验证的用户关联的openid,个人资料和电子邮件数据。 该方法需要从signIn()方法的响应返回的会话令牌。 最后,您已经告诉该函数回调redirectUri ,在创建应用程序时,将该redirectUri设置为Okta中的受信任重定向源。

在此承诺的then条件下,您将接收到的id令牌并将其在本地存储中设置为okta_id_token 。 如果一切正常,则将用户重定向到个人资料页面。

如果响应的状态不是200,则只会抛出一个错误,表明它无法处理其他任何状态。 最后, signIn()方法调用的失败条件只是将所有错误记录到控制台。

简化登录

在此过程中,有两件事可以使该组件更好用:可以按Enter键登录而不用单击“登录”按钮,并且如果该人尝试进入登录页面,甚至不显示登录表单。他们已经登录时。

为此,添加一个方法,如果用户已经登录,则将用户直接带到个人资料页面。与React组件一样,Stencil组件也具有生命周期方法。 取而代之的componentWillMount()的反应,模板有一个componentWillLoad()方法,所以这是什么,你会在这里使用。

componentWillLoad() {
  let idToken = localStorage.getItem('okta_id_token');
  if (idToken) {
    this.history.push('/profile', {});
  }
}

简而言之,您要做的就是从本地存储中读取令牌。 如果存在,则假定它们已登录并将其重定向到个人资料页面。

使此登录表单更易于使用的最后一件事是添加使用Enter键提交表单的功能。 Stencil具有一些内置的按键监听器。 在这种情况下,请使用“ keydown.enter”侦听器。 在导入Component的最顶层import语句中导入@Listen()装饰器。

import { Component, Prop, State, Element, Listen } from '@stencil/core';

然后在componentWillLoad()函数下面添加一个用于'keydown.enter'事件的处理程序。

@Listen('keydown.enter')
handleEnter() {
  this.login();
}

更新资料页面

既然您拥有一个不错的登录页面,请更新个人资料页面,以便在用户登录后显示用户的声明。

首先,您需要输入用户声明的类型。因此,在app-profile文件夹中创建一个名为AppUser.tsx的新文件。 内容很简单,但是很长。 我只是查看了存储在localStorage中的令牌中的所有声明,并创建了与其匹配的接口。 因此, AppUser.tsx文件如下:

interface AppUser {
  sub: string;
  name: string;
  locale: string;
  email: string;
  ver: number;
  iss: string;
  aud: string;
  iat: number;
  exp: number;
  jti: string;
  amr: string[];
  idp: string;
  nonce: string;
  nickname: string;
  preferred_username: string;
  given_name: string;
  family_name: string;
  zoneinfo: string;
  updated_at: number;
  email_verified: boolean;
  auth_time: number;
}

在为您的配置文件的用户对象声明类型后,更新app-profile.tsx文件。

顶部的导入应如下所示:

import { Component, Prop, State } from '@stencil/core';
import { RouterHistory } from '@stencil/router';

删除@Prop()行以进行match并替换为:

@Prop() history: RouterHistory;
@State() user: AppUser;
@Prop({ context: 'isServer' }) private isServer: boolean;

isServer属性是一个特殊属性。 由于Stencil支持预渲染,并且在预渲染期间localStorage可能不可用,因此您需要将localStorage调用包装在if(!isServer){} ,以确保它将为生产而构建。 这不应该阻止它的正常运行,而只是构建过程中的一项工作。

对于componentWillLoad()方法,只需从本地存储中的“ okta_id_token”中读取用户信息:

componentWillLoad() {
  if (!this.isServer) {
    let token = JSON.parse(localStorage.getItem('okta_id_token'));
    if (token) {
      this.user = token.claims;
    } else {
      this.history.push('/login', {});
    }
  }
}

这也是个人资料页面的保护者,它只是检查令牌是否存在。 如果是这样,它将从中加载索赔。 如果不是,它将重定向到登录页面。

对于render()方法,更改它以在列表中显示声明。

render() {
  if (this.user) {
  let keys = Object.keys(this.user);
  return <div class="app-profile">
      <h2>User Claims</h2>
      <ul>
        {keys.map(key => <li><span>{key}</span>: {this.user[key]}</li>)}
      </ul>
      <button onClick={this.logout}>
        Logout
      </button>
    </div>;
  }
}

剩下的唯一事情就是添加logout()方法。 这只会从本地存储中删除令牌并重新加载页面,这将迫使componentWillLoad()将用户重定向到登录页面。

logout() {
  if (!this.isServer) {
    localStorage.removeItem('okta_id_token');
    location.reload();
  }
}

设置登录路径

剩下的唯一事情就是将通往登录组件的路由添加到应用程序中,以便用户可以到达那里。

components/my-app/my-app.tsx文件中,在stencil-router组件内部添加路由,以便最后一部分如下所示:

<stencil-router>
  <stencil-route url="/" component="app-home" exact={true} />
  <stencil-route url="/profile" component="app-profile" />
  <stencil-route url="/login" component="app-auth" />
</stencil-router>

您还需要更新主页上链接的路由。 在components/app-home/app-home.tsxstencil-route-link元素的url更新为不再传递url参数。

<stencil-route-link url="/profile">
  <button>
    Profile page
  </button>
</stencil-route-link>

而已! 现在,您应该能够运行该应用程序,单击个人资料页面,重定向到登录页面,并在登录后重定向回个人资料页面。个人资料页面应显示您的所有声明。已验证。

恭喜,您现在拥有一个带有身份验证的PWA,可以征服世界了!

添加样式

作为额外的功劳,您可能想在登录表单和个人资料页面中添加一些样式。 以下是我在app-auth.css登录页面的样式表:

.app-auth {
  width: 30%;
  margin: 2rem auto;
}
.app-auth .form-item {
  padding: .25rem;
}
.app-auth label {
  width: 100%;
  font-size: 1rem;
  color: #999;
}

.app-auth label input {
  width: 97%;
  border-radius: .25rem;
  font-size: 1.5rem;
}

.app-auth .form-actions {
  text-align: right;
}

最后,在app-profile.css仅提供一些简单的样式来加粗每个项目的标签。

.app-profile {
  padding: 10px;
}

.app-profile ul li span {
  font-weight: bold;
}

现在,当您运行该应用程序时,您将看到一个样式精美的应用程序,可随时用于网络!

模具应用程序登录页面

学到更多

要了解有关PWA的更多信息,请在Okta开发者博客上查看Matt Raible的PWA终极指南

如果您想了解有关Ionic应用程序的更多信息,请查看Matt的有关构建Ionic应用程序的博客文章。

您可以从Brandon Parise的帖子中了解有关使用VueJS构建基本的CRUD应用程序的信息

最后,在这里您可以看到如何使用Node和React设置用户注册

与往常一样,如果您有任何问题,可以在下面评论或在Twitter @leebrandt上打我,并且不要忘记关注@OktaDev,以获取我们社区的精彩内容以及有关Okta开发人员平台的所有新闻!

From: https://www.sitepoint.com/how-to-add-auth-to-your-pwa-with-okta-and-stencil/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用Okta集成Spring Boot应用程序,你可以遵循以下步骤: 1. 首先,你需要在Okta注册你的应用程序以获取客户端ID和客户端密钥等信息。在Okta的管理控制台,选择“应用程序”选项卡,在“创建应用程序”下拉菜单选择“Web”应用程序类型,并输入应用程序的详细信息。 2. 在Spring Boot应用程序添加Okta Starter依赖项。在Maven项目添加以下依赖项: ``` <dependency> <groupId>com.okta.spring</groupId> <artifactId>okta-spring-boot-starter</artifactId> </dependency> ``` 3. 在应用程序配置文件添加以下属性: ``` okta.oauth2.issuer=https://${yourOktaDomain}/oauth2/default okta.oauth2.client-id=${clientId} okta.oauth2.client-secret=${clientSecret} okta.oauth2.scopes=openid,email,profile okta.oauth2.redirect-uri=${baseUrl}/authorization-code/callback ``` 将`${yourOktaDomain}`、`${clientId}`、`${clientSecret}`和`${baseUrl}`替换为你的Okta域名、客户端ID、客户端密钥和应用程序基本URL。 4. 在Spring Boot应用程序创建一个Okta配置类,并标注为@Configuration和@EnableWebSecurity。在这个类,你可以配置Spring Security和Okta集成的细节。以下是一个示例配置类: ``` @Configuration @EnableWebSecurity public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/login**", "/error**") .permitAll() .anyRequest() .authenticated() .and() .oauth2Login(); } } ``` 5. 在你的Spring Boot应用程序,你可以使用Okta的Spring Security集成来保护你的Web资源。例如,你可以在应用程序使用@PreAuthorize注解来限制只有经过身份验证的用户才能访问特定的URL。 ``` @GetMapping("/protected") @PreAuthorize("hasAuthority('SCOPE_profile')") public String getProtectedResource() { return "This is a protected resource"; } ``` 完成上述步骤后,你的Spring Boot应用程序就可以使用Okta进行身份验证和授权了。当用户尝试访问受保护的URL时,他们将被重定向到Okta进行身份验证。如果身份验证成功,则用户将被重定向回你的应用程序,并能够访问受保护的资源。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值