加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

使用Thinktecture的IdentityServer STS保护对REST端点的AJAX调用

发布时间:2020-12-16 02:50:00 所属栏目:百科 来源:网络整理
导读:我有一些电视剧正在对ServiceStack REST服务进行调用,我用一个开箱即用的IdentityServer STS来保护它. 我正在对REST端点进行AJAX调用,我不确定如何设置登录过程来获取安全令牌. REST端点与进行呼叫的网站位于不同的域中.到目前为止我发现的信息似乎都围绕着
我有一些电视剧正在对ServiceStack REST服务进行调用,我用一个开箱即用的IdentityServer STS来保护它.

我正在对REST端点进行AJAX调用,我不确定如何设置登录过程来获取安全令牌. REST端点与进行呼叫的网站位于不同的域中.到目前为止我发现的信息似乎都围绕着客户端对安全资源进行调用的过程获得302重定向到身份服务器登录页面,然后在成功进行身份验证后获得302重定向到域或者根据配置回复.我已经正确地连接了所有这些,如果我只是浏览REST服务,它会很有效.但是对于我的网络应用程序,AJAX和302s并不是最好的朋友,所以理想情况下我认为我想要的是来自同一ServiceStack网站的REST端点,该端点获取用户名和密码并返回安全令牌而不用任何重定向的复杂性(我将处理我的Web应用程序本身中的401重定向,当我关闭web.config中的passiveRedirectEnabled时,我将获得该重定向).有关如何使用IdentityServer实现此目的的任何想法?

干杯,
克林特.

解决方法

使用完整的REST端点完成答案:

在ServiceStack Web应用程序中:

在AppHost.cs中路由到登录端点,例如:

public override void Configure(Container container)
{
    Routes.Add<Logon>("/logon","POST");
}

然后是一个简单的用户名/密码请求DTO

public class Logon
{
    public string UserName { get; set; }
    public string Password { get; set; }
}

并回应DTO

响应DTO只需要处理POST – 是的,您可以添加URL /密码
作为GET请求的URL中的参数,但这听起来不像是推荐的.
实际上,您通常可能会将此信息放在HTTP请求的Authorization标头中
但这会让你在ServiceStack中的工作变得更难.

public class LogonService : Service
{
    public object Post(Logon request)
    {
        var securityToken = GetSaml2SecurityToken(request.UserName,request.Password,"https://myserver/identityserverwebapp/issue/wstrust/mixed/username","http://myserver/servicestackwebapp/");

        return SerializeRequestSecurityTokenResponse(securityToken);
    }

    private RequestSecurityTokenResponse GetSaml2SecurityToken(string username,string password,string endpointAddress,string realm)
    {
        var factory = new WSTrustChannelFactory(new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential),new EndpointAddress(endpointAddress))
        {
            TrustVersion = TrustVersion.WSTrust13
        };

        factory.Credentials.UserName.UserName = username;
        factory.Credentials.UserName.Password = password;

        var channel = (WSTrustChannel)factory.CreateChannel();
        RequestSecurityTokenResponse requestSecurityTokenResponse;

        channel.Issue(new RequestSecurityToken
        {
            TokenType = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0",AppliesTo = new EndpointReference(realm),RequestType = RequestTypes.Issue,KeyType = KeyTypes.Bearer,},out requestSecurityTokenResponse);

        return requestSecurityTokenResponse;
    }

    private string SerializeRequestSecurityTokenResponse(RequestSecurityTokenResponse requestSecurityTokenResponse)
    {
        var serializer = new WSTrust13ResponseSerializer();
        var context = new WSTrustSerializationContext(FederatedAuthentication.FederationConfiguration.IdentityConfiguration.SecurityTokenHandlerCollectionManager);
        var stringBuilder = new StringBuilder(128);

        using (var writer = XmlWriter.Create(new StringWriter(stringBuilder),new XmlWriterSettings { OmitXmlDeclaration = true}))
        {
            serializer.WriteXml(requestSecurityTokenResponse,writer,context);
            writer.Flush();
            return stringBuilder.ToString();
        }
    }
}

ServiceStack Web应用程序Web.config看起来应该与此非常相似:

<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection,System.IdentityModel,Version=4.0.0.0,Culture=neutral,PublicKeyToken=B77A5C561934E089" />
    <section name="system.identityModel.services" type="System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection,System.IdentityModel.Services,PublicKeyToken=B77A5C561934E089" />
  </configSections>
  <location path="FederationMetadata">
    <system.web>
      <authorization>
        <allow users="*" />
      </authorization>
    </system.web>
  </location>
  <!-- to allow the logon route without requiring authentication first. -->
  <location path="logon">
    <system.web>
      <authorization>
        <allow users="*" />
      </authorization>
    </system.web>
  </location>
  <system.web>
    <httpHandlers>
      <add path="*" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory,ServiceStack" verb="*" />
    </httpHandlers>
    <compilation debug="true" />
    <authentication mode="None" />
    <authorization>
      <deny users="?" />
    </authorization>
    <httpRuntime targetFramework="4.5" requestValidationMode="4.5" />
  </system.web>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
        <add name="WSFederationAuthenticationModule" type="System.IdentityModel.Services.WSFederationAuthenticationModule,PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />
        <add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule,PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />
    </modules>
    <validation validateIntegratedModeConfiguration="false" />
    <handlers>
      <add path="*" name="ServiceStack.Factory" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory,ServiceStack" verb="*" preCondition="integratedMode" resourceType="Unspecified" allowPathInfo="true" />
    </handlers>
  </system.webServer>
  <system.identityModel>
    <identityConfiguration>
      <audienceUris>
        <add value="http://myserver/servicestackwebapp/" />
      </audienceUris>
      <issuerNameRegistry type="System.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry,PublicKeyToken=b77a5c561934e089">
        <trustedIssuers>
          <add thumbprint="B6E05E14243FB7D76D5B660532520FB94679AA01" name="http://mycertificatefriendlyname" />
        </trustedIssuers>
      </issuerNameRegistry>
      <certificateValidation certificateValidationMode="None" />
      <securityTokenHandlers>
        <securityTokenHandlerConfiguration saveBootstrapContext="true" />
      </securityTokenHandlers>
    </identityConfiguration>
  </system.identityModel>
  <system.identityModel.services>
    <federationConfiguration>
      <cookieHandler requireSsl="false" />
      <wsFederation passiveRedirectEnabled="false" issuer="https://myserver/identityserverwebapp/issue/wsfed" realm="http://myserver/servicestackwebapp/" requireHttps="false" />
    </federationConfiguration>
  </system.identityModel.services>
</configuration>

最后,使用REST端点验证一个简单的Javascript客户端应用程序,将用户名和密码POST到servicestackwebapp的登录端点,然后当您收到响应时,将其发回到领域 – 这样做会设置FedAuth cookie对于您当前的会话,您不必再考虑令牌管理客户端了.

$.ajax({
    type: "POST",url: "/servicestackwebapp/logon",dataType: "text",data: { UserName: "myuser",Password: "mypassword" },success: function (data) {
        $.ajax({
            type: "POST",url: "/servicestackwebapp/",data: "wa=wsignin1.0&wresult=" + encodeURIComponent(data)
        });
    }
});

此外,我应该注意,上面的所有HTTP端点都应该通过HTTPS – 不要像我在我的示例中所做的那样愚蠢,并通过HTTP发送明文声明.

在我实施我的解决方案之后,我发现了这个:http://msdn.microsoft.com/en-us/library/hh446531.aspx…我希望我之前找到它,但是知道我已经实现了类似于Microsoft示例的东西 – 我们在将它们转换为简单Web令牌时分歧 – 我将其保留为SAML令牌,并且令人放心.将(序列化的)传递给客户端.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读