从AuthenticationHandler返回自定义对象

时间:2017-09-28 11:58:14

标签: c# .net-core

我正在尝试使用来自第三方提供商的自定义身份验证 - 并将其链接到.net core 2.0。

我已经创建了基础知识...... “TokenAuthenticationHandler”

public class TokenAuthenticationHandler : AuthenticationHandler<TokenAuthenticationOptions>
{
    public TokenAuthenticationHandler(IOptionsMonitor<TokenAuthenticationOptions> options, 
        ILoggerFactory logger, 
        UrlEncoder encoder, 
        ISystemClock clock) 
        : base(options, logger, encoder, clock)
    {

    }

    protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        // Get the API key
        var token = new AuthToken
        {
            ApiKey = GetKeyValue(Options.ApiKeyName),
            Username = GetKeyValue(Options.UsernameKeyName),
            Password = GetKeyValue(Options.PasswordKeyName),
            IpAddress = Context.Connection.RemoteIpAddress.ToString()
        };

        // setup the auth repo and identity
        var authRepo = new AuthRepository(token);
        var identity = new TokenIdentity(authRepo);

        // Check the identity
        if (identity.IsAuthenticated)
        {
            var ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), null, "exttoken");
            var result = AuthenticateResult.Success(ticket);
            return result;
        }

        // Authentication failed
        return AuthenticateResult.NoResult();
    }

    protected string GetKeyValue(string keyName)
    {
        return Request
            .Headers?
            .SingleOrDefault(a => a.Key == keyName)
            .Value
            .FirstOrDefault();
    }
}

“TokenAuthenticationOptions”

public class TokenAuthenticationOptions : AuthenticationSchemeOptions
{
    public string ApiKeyName { get; set; } = "X-APIKEY";
    public string UsernameKeyName { get; set; } = "X-USERNAME";
    public string PasswordKeyName { get; set; } = "X-PASSWORD";
    public string CookieName { get; set; } = "MTDATA";
}

这一切都很完美,用户是否经过身份验证(通过401错误),并且控制器被调用...

然而......我不知何故需要从这里获取“AuthRepository”对象 - 回到我的控制器,因为这是我与第三方系统交互的方式。

我尝试使用自定义IIdentity实现解决此问题,如下所示;

public class TokenIdentity : IIdentity
{
    public string AuthenticationType { get; } = "exttoken";
    public bool IsAuthenticated { get; }
    public string Name { get; }
    public AuthRepository AuthenticationRepository { get; }

    public TokenIdentity(AuthRepository authRepository)
    {
        AuthenticationRepository = authRepository;
        IsAuthenticated = AuthenticationRepository.Authenticate();
        if (IsAuthenticated)
            Name = AuthenticationRepository.GetCurrentUser()?.Name;
    }
}

在我的控制器中,然后我尝试使用HttpContext.User.Identity获取身份 - 但是在控制器内的此时,我的客户“TokenIdentity”已经转换为“ClaimsPrinciple”,列出的错误是:

  

System.InvalidCastException:'无法转换类型的对象   键入'System.Security.Claims.ClaimsIdentity'   'X.X.X.WebAPI.Authentication.TokenIdentity''。

有什么想法吗?尝试再次调用authRepository不是一种选择,因为存在与授权和访问请求相关的开销 - 因此,我继续使用现有的authRepo对象至关重要。

1 个答案:

答案 0 :(得分:1)

通过对HandleAuthenticateAsync进行以下更改解决了此问题;

$filename=$_FILES["file"]["tmp_name"];      

     if($_FILES["file"]["size"] > 0)
     {
        ini_set("auto_detect_line_endings", true);
        $file = fopen($filename, "r");
        $flag = true;
        $row = 1;

        while (($getData = fgetcsv($file, 10000, ";")) !== FALSE)
         {
            if($flag) { $flag = false; continue; }

            $sql = "INSERT into public.fulldict (studiennr,studienname,formular,formularmodul,modul_id,titel_der_ableitung,abl_version,feldname,hilfetext,variablenname,pflichtfeld,feldtyp,feldlaenge,min_wert,max_wert,einheit,code,read_only,exeptional_values,passiv) 
                    values ('".pg_escape_string($getData[0])."','".pg_escape_string(($getData[1]))."','".pg_escape_string(($getData[2]))."','".pg_escape_string(($getData[3]))."','".pg_escape_string(($getData[4]))."','".pg_escape_string(($getData[5]))."','".pg_escape_string(($getData[6]))."','".pg_escape_string(($getData[7]))."','".pg_escape_string(($getData[8]))."','".pg_escape_string(($getData[9]))."','".pg_escape_string(($getData[10]))."','".pg_escape_string(($getData[11]))."','".pg_escape_string(($getData[12]))."','".pg_escape_string(($getData[13]))."','".pg_escape_string(($getData[14]))."','".pg_escape_string(($getData[15]))."','".pg_escape_string(($getData[16]))."','".pg_escape_string(($getData[17]))."','".pg_escape_string(($getData[18]))."','".pg_escape_string(($getData[19]))."')";
                $result = $con -> prepare($sql);
                $result -> execute();
            if(!isset($result))
            {
                echo "<script type=\"text/javascript\">
                        alert(\"Invalid File:Please Upload CSV File.\");
                        window.location = \"upload.php\"
                      </script>";   
            }
            else {
                echo "<script type=\"text/javascript\">
                    alert(\"CSV File has been successfully Imported.\");
                    window.location = \"upload.php\"
                </script>"; 
            }

         }
         fclose($file); 
         ini_set("auto_detect_line_endings", false);
     }

然后我可以通过以下方式访问authRepo:

    char* str =
    "\
    a-a-a-a\
    differing the text, because that was the lecture thing\
    the text has been changed\
    I know!\
    the text has been changed\
    ";

将此对象存储在// Check the identity if (identity.IsAuthenticated) { var ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), null, "exttoken"); var result = AuthenticateResult.Success(ticket); Request.HttpContext.Items["auth"] = authRepo; return result; }

中是一个好主意