带有Silhouette

时间:2015-10-27 08:53:30

标签: playframework silhouette

使用play-framework + silhouette成功进行google-web登录后,我希望能够使用ajax请求进行访问。 This answer说要使用2个环境中的2个控制器。

 Environment[User, SessionAuthenticator]
 Environment[User, JWTAuthenticator]
  1. 如何将Web身份验证(SessionAuthenticator)与使用JWTAuthenticator的其他部分“链接”
  2. ajax客户端是否可以使用会话cookie中的数据构建JWT标头(如何)?

2 个答案:

答案 0 :(得分:0)

Implement aouth2 with User define tables.
 public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        ConfigureAuth(app);
        app.MapSignalR();

        HttpConfiguration config = new HttpConfiguration();
        WebApiConfig.Register(config);
        app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
        app.UseWebApi(config);
    }
}
call startup class 
ConfigureOAuth(app);
  public void ConfigureOAuth(IAppBuilder app)
    {
        OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
        {
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
            Provider = new SimpleAuthorizationServerProvider(),
             RefreshTokenProvider = new SimpleRefreshTokenProvider()
        };

        // Token Generation
        app.UseOAuthAuthorizationServer(OAuthServerOptions);
        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

    }
Provider -----
  public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
    public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
    {
        context.Validated();
    }

    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {

        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });

        using (AuthRepository _repo = new AuthRepository())
        {
            var user = await _repo.FindUser(context.UserName, context.Password);

            if (user == null)
            {
                context.SetError("invalid_grant", "The user name or password is incorrect.");
                return;
            }



        //ClaimsIdentity oAuthIdentity = await _repo.CreateIdentityAsync(user,
        //      context.Options.AuthenticationType);
        //ClaimsIdentity cookiesIdentity = await _repo.CreateIdentityAsync(user,
        //    CookieAuthenticationDefaults.AuthenticationType);
        //AuthenticationProperties properties = CreateProperties(user.UserName);
        //AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
        //context.Validated(ticket);
        //context.Request.Context.Authentication.SignIn(cookiesIdentity);
 }
           var identity = new ClaimsIdentity(context.Options.AuthenticationType);
        identity.AddClaim(new Claim("sub", context.UserName));
        identity.AddClaim(new Claim("role", "user"));

        context.Validated(identity);

    }

    public override async Task GrantRefreshToken( OAuthGrantRefreshTokenContext context)

    {
        var originalClient = context.Ticket.Properties.Dictionary["as:client_id"];
        var currentClient = context.OwinContext.Get<string>("as:client_id");

        // enforce client binding of refresh token
        if (originalClient != currentClient)
        {
            context.Rejected();
            return;
        }

        // chance to change authentication ticket for refresh token requests
        var newId = new ClaimsIdentity(context.Ticket.Identity);
        newId.AddClaim(new Claim("newClaim", "refreshToken"));

        var newTicket = new AuthenticationTicket(newId, context.Ticket.Properties);
        context.Validated(newTicket);
    }
}

public class SimpleRefreshTokenProvider : IAuthenticationTokenProvider
{
    private static ConcurrentDictionary<string, AuthenticationTicket> _refreshTokens = new ConcurrentDictionary<string, AuthenticationTicket>();


    public   async Task CreateAsync(AuthenticationTokenCreateContext context)
    {
        var guid = Guid.NewGuid().ToString();

        // maybe only create a handle the first time, then re-use
        _refreshTokens.TryAdd(guid, context.Ticket);

        // consider storing only the hash of the handle
        context.SetToken(guid);
    }

    public   async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
    {
        AuthenticationTicket ticket;
        if (_refreshTokens.TryRemove(context.Token, out ticket))
        {
             context.SetTicket(ticket);
        }
    }

    public void Create(AuthenticationTokenCreateContext context)
    {
        var guid = Guid.NewGuid().ToString();

        // maybe only create a handle the first time, then re-use
        _refreshTokens.TryAdd(guid, context.Ticket);

        // consider storing only the hash of the handle
        context.SetToken(guid);
    }

    public void Receive(AuthenticationTokenReceiveContext context)
    {
        AuthenticationTicket ticket;
        if (_refreshTokens.TryRemove(context.Token, out ticket))
        {
            context.SetTicket(ticket);
        }
    }
}
 Repo-------------
  public class UserManagerService : UserManager<User>, IUserManagerService<User>
{

    public UserManagerService(IUserStore<User> userStore)
        : base(userStore)
    {
        this.UserValidator = new UserValidator<User>(this) { AllowOnlyAlphanumericUserNames = false };
    }

    public new IUserStore<User> Store
    {
        get { return base.Store; }
    }


}


  public class AuthRepository : IDisposable
  {
   private AuthContext _ctx;

   private UserManager<User> _userManager;

   public AuthRepository() 
   {
       _ctx = new AuthContext();
       _userManager =  new UserManager<User>(new UserStore<User>(_ctx));
   }
   //public async Task<IdentityResult> RegisterUser(UserModel userModel)
   //{
   //    IdentityUser user = new IdentityUser
   //    {
   //        UserName = userModel.UserName
   //    };

   //    var result = await _userManager.CreateAsync(user, userModel.Password);

   //    return result;
   //}

   public async Task<User> FindUser(string userName, string password)
   {
       User user = await _userManager.FindAsync(userName, password);

       return user;
   }

   public void Dispose()
   {
       _ctx.Dispose();
       _userManager.Dispose();

   }
   }


  public class AuthContext : DbContext
 {
   public AuthContext()
       : base("ObjectContext")
   {
   }
   protected override void OnModelCreating(DbModelBuilder modelBuilder)
   {

       modelBuilder.Entity<IdentityRole>().HasKey<string>(i => i.Id).ToTable("Roles");
       modelBuilder.Entity<IdentityUser>().HasKey<string>(i => i.Id).ToTable("Users");
       modelBuilder.Entity<User>().HasKey<string>(i => i.Id).ToTable("Users");
       modelBuilder.Entity<IdentityUserClaim>().HasKey<int>(i => i.Id).ToTable("UserClaims");
       modelBuilder.Entity<IdentityUserLogin>().HasKey(q => new { q.LoginProvider, q.UserId, q.ProviderKey }).ToTable("UserLogins");
       modelBuilder.Entity<IdentityUserRole>().HasKey(q => new { q.RoleId, q.UserId }).ToTable("UserRoles");

       base.OnModelCreating(modelBuilder);

   }
}

答案 1 :(得分:0)

这不是一个完整的技术解决方案,但这些是我的见解:

  1. 可以在“登录响应”中嵌入cookie会话和X-Auth-Token。它们被放置在具有不同名称的标题上。
  2. 要生成两者,您需要登录控制器上的2个相关“环境”。
  3. 登录后,您的客户将拥有两个cookie(无论成本是多少),但之后对SilhouetteController的安全请求仅处理每个控制器的一种类型的auth(使用“com.mohiva”%%“play-silhouette”%“2.0”我认为它在Silhouette 3.0中发生了变化)