Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Pulsar instalar, y .Net procede a actualizar las librerías para usar la autenticación por
Token.
2. Crear en la BD una tabla que almacenara los datos de los clientes autorizados para acceder
a los servicios Api, llamada UsuariosApi que tenga la siguiente estructura.
Codigo int
UserName varchar(20)
Clave Varchar(80)
Nombre varchar(160)
Rol varchar(80)
3. Crear en la capa de entidades carpeta Core la clase que mapee a los usuarios del servicio
web
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization;
namespace ABB.Catalogo.Entidades.Core
{
[DataContract]
[Serializable]
}
}
4. Crear en la capa de entidades Carpeta Core dos clase TokenResponse, para
guardar la clave token creada, y CustomError para guardar los errores.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ABB.Catalogo.Entidades.Core
{
public class TokenResponse
{
public string User { get; set; }
public string Token { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ABB.Catalogo.Entidades.Core
{
public class CustomError
{
public int Codigo { get; set; }
public string Detalle { get; set; }
}
}
namespace WebServicesAbb.Controllers
{
public class AuthController : ApiController
{
}
}
namespace WebServicesAbb.Controllers
{
public class AuthController : ApiController
{
[HttpPost]
public IHttpActionResult Valida([FromBody] UsuariosApi usuarioAutentica)
{
//validaciones antes de procesar
if (string.IsNullOrEmpty(usuarioAutentica.Clave)
|| string.IsNullOrEmpty(usuarioAutentica.UserName))
{
return BadRequest("Debe enviar la clave o codigo");
}
}
var expireTime = ConfigurationManager.AppSettings["JWT_EXPIRE_MINUTES"];
//crear la semilla
string clave = ConfigurationManager.AppSettings["JWT_SECRET_KEY"];
byte[] claveEnBytes = Encoding.UTF8.GetBytes(clave);
//para convertir la clave que esta como un arreglo de bytes en simetrica
SymmetricSecurityKey key = new SymmetricSecurityKey(claveEnBytes);
//payload
var _Claims = new[] {
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.NameId,
usuarioAutentica.UserName.ToString()),
//new Claim("nombre", "David"),
new Claim("nombre", usuarioapi.Nombre),
// new Claim("apellidos", "Espinoza"),
new Claim("rol", usuarioapi.Rol),
// new Claim(JwtRegisteredClaimNames.Email,
"despinoza@avanza....com"),
// new Claim(ClaimTypes.Role, "admin")
};
//encriptador
JwtSecurityToken jwtSecurityToken = new JwtSecurityToken(
audience: ConfigurationManager.AppSettings["JWT_AUDIENCE_TOKEN"],
issuer: ConfigurationManager.AppSettings["JWT_ISSUER_TOKEN"],
expires: DateTime.UtcNow.AddMinutes(Convert.ToInt32(expireTime)),
//DateTime.Now.AddMinutes(10),
claims: _Claims,
signingCredentials: cred
);
});
}
}
}
Para validar las credenciales del usuario Web Api, se debe crear en la
capa LogicaNegocios y AccesoDatos las respectivas clases de
UsuarioApiLN y UsuarioApiAD con su método de BuscaUsuarioApi() que
recibe una clase de tipo UsuarioApi que trae las credenciales en sus
atributos UserName y Clave.
namespace ABB.Catalogo.LogicaNegocio.Core
{
public class UsuarioApiLN : BaseLN
{
public UsuariosApi BuscaUsuarioApi(UsuariosApi PamUsuarioApi)
{
return new UsuarioApiAD().BuscaUsuarioApi(PamUsuarioApi);
}
}
}
namespace ABB.Catalogo.AccesoDatos.Core
{
public class UsuarioApiAD
{
public UsuariosApi BuscaUsuarioApi(UsuariosApi ParamUserApi)
{
UsuariosApi entidad = new UsuariosApi();
conexion.Close();
}
}
return entidad;
}
}
}
7. Proceso para filtrar cuando recuperamos el Token, nos permite comparar el token
generado con el enviado por el cliente y poder filtar los pedidos valido. Crear en el
proyecto web api una carpeta llamada Filters y dentro una clase llamada FIlterJWT
con métodos para filtrar los tokens válidos.
La clase quedaría asi. Debe resolverse los using respectivos cuando aparezcan los
errores.
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
namespace WebServicesAbb.Filters
{
public class FIlterJWT : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage
request, CancellationToken cancellationToken)
{
HttpStatusCode statusCode;
string token;
try
{
SecurityToken securityToken;
var tokenHandler = new
System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler();
TokenValidationParameters validationParameters = new
TokenValidationParameters()
{
ValidAudience = audienceToken,
ValidIssuer = issuerToken,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
IssuerSigningKey = key
};
validationParameters,
out
securityToken);
HttpContext.Current.User = tokenHandler.ValidateToken(token,
validationParameters,
out
securityToken);
}
}
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
Se agrega la línea : config.MessageHandlers.Add(new FIlterJWT());
Y quedara así
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.MessageHandlers.Add(new FIlterJWT());
}
namespace WebServicesAbb.Controllers
{
[Authorize]
public class UsuariosController : ApiController
{
// GET: api/Usuarios
[HttpGet]
public IEnumerable<Usuarios> Get()
{
List<Usuarios> usuarios = new List<Usuarios>();
usuarios = new UsuariosLN().ListarUsuarios();
return usuarios;
}
[HttpGet]
public IHttpActionResult Get([FromUri] string pUsuario, [FromUri] string
pPassword)
{
if (pUsuario == null || pPassword == null)
{
return BadRequest ("Debe enviar las credenciales correctas");
}
try
{
UsuariosLN usuario = new UsuariosLN();
var rsp = usuario.GetUsuarioId(pUsuario, pPassword);
return Ok(Convert.ToString(rsp));
// return usuario.GetUsuarioId(pUsuario, pPassword);
}
catch (Exception ex)
{
string innerException = (ex.InnerException == null) ? "" :
ex.InnerException.ToString();
//Logger.paginaNombre = this.GetType().Name;
//Logger.Escribir("Error en Logica de Negocio: " + ex.Message + ". "
+ ex.StackTrace + ". " + innerException);
throw ex;
}
[HttpGet]
// public Usuarios GetUserId([FromUri] int IdUsuario)
public IHttpActionResult GetUserId([FromUri] int IdUsuario)
{
if (IdUsuario <= 0)
{
return BadRequest("el Id debe ser mayor que 0");
}
try
{
Usuarios usu = new Usuarios();
UsuariosLN usuario = new UsuariosLN();
usu= usuario.BuscaUsuarioId(IdUsuario);
return Ok(usu);
}
catch (Exception ex)
{
string innerException = (ex.InnerException == null) ? "" :
ex.InnerException.ToString();
//Logger.paginaNombre = this.GetType().Name;
//Logger.Escribir("Error en Logica de Negocio: " + ex.Message + ". "
+ ex.StackTrace + ". " + innerException);
throw;
}
// POST: api/Usuarios
[HttpPost]
// public void Post([FromBody]Usuarios value)
public IHttpActionResult Post([FromBody]Usuarios value)
{
if (value.CodUsuario == null)
{
return BadRequest("CodUsuario es nulo");
}
if (value.ClaveTxt == null)
{
return BadRequest("ClaveTxt es nulo");
}
if (value.Nombres == null)
{
return BadRequest("Nombres es nulo");
}
if (value.IdRol <= 0)
{
return BadRequest("IdRol es nulo");
}
Usuarios usuario = new UsuariosLN().InsertarUsuario(value);
return Ok(usuario);
}
// PUT: api/Usuarios/5
[HttpPut]
// DELETE: api/Usuarios/5
[HttpDelete]
public void Delete(int id)
{
}
}
}
En el Controlador Api Productos (este controller api solo tiene implementado el método
get, realizar los otros métodos.)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using ABB.Catalogo.Entidades.Core;
using ABB.Catalogo.LogicaNegocio.Core;
namespace WebServicesAbb.Controllers
{
[Authorize]
public class ProductosController : ApiController
{
// GET: api/Productos
[HttpGet]
public IEnumerable<Producto> Get()
{
List<Producto> catalogo = new List<Producto>();
catalogo = new ProductoLN().ListarProductos();
return catalogo;
}
// GET: api/Productos/5
public string Get(int id)
{
return "value";
}
// POST: api/Productos
public void Post([FromBody]string value)
{
}
// PUT: api/Productos/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE: api/Productos/5
public void Delete(int id)
{
}
}
}
Para Microsoft.AspNet.WebApi.Client
16. En el web config del proyecto cliente llamado ABB.Catalogo.ClienteWeb actualizar
el tag <appSettings> poniendo allí las credenciales del UsuarioApi. (este es el
usuario que podrá invocar los servicios web)
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<add key="cnnSql" value="SQL" />
<add key="UsuApiCodigo" value="0" />
<add key="UsuApiUserName" value="ggutierrez" />
<add key="UsuApiClave" value="abc1234" />
<add key="UsuApiNombre" value="Gladys Gutierrez" />
<add key="UsuApiRol" value="Admin" />
</appSettings>
Los keys UsuApiCodigo, UsuApiUserName, UsuApiClave, UsuApiNombre, UsuApiRol
deben tener valores validos existente en la tabla UsuariosApi de la BD.
Este método invoca el controlador Auth; del web servicies para generar el
token. Se envía como parámetros las credenciales del usuario autorizado que
fueron puesto en el web config; retorma un objeto de tipo TokenResponse con
el valor de la clave Token.
Poner el token en la cabecera cuando se invoca los metos get, post del web
services.
Como se ve En el método Index() se crea una instancia de la clase
TokenResponse, y se llama al método Respuesta(), el token devuelto se coloca
en la cabecera de la llamada el método del web service; esto hace con la
clausula
usuario.Headers[HttpRequestHeader.Authorization]= "Bearer " +
tokenrsp.Token;
return View(listausuarios);
}
// GET: Usuarios/Details/5
public ActionResult Details(int id)
{
return View();
}
// GET: Usuarios/Create
public ActionResult Create()
{
Usuarios usuario = new Usuarios();// se crea uns instancia de la clase
usuario
// POST: Usuarios/Create
[HttpPost]
public ActionResult Create(Usuarios collection)
{
return RedirectToAction("Index");
}
catch
{
return View();
}
}
// GET: Usuarios/Edit/5
public ActionResult Edit(int id)
{
return View(users);
}
// POST: Usuarios/Edit/5
[HttpPost]
// [HttpPut]
public ActionResult Edit(int Id,Usuarios collection)
{
string controladora = "Usuarios";
collection.IdUsuario = Id;
collection.ClaveTxt = "";
collection.Clave = null;
collection.DesRol = "";
if (result.IsSuccessStatusCode)
{
return RedirectToAction("Index");
}
return RedirectToAction("Index");
}
// }
// return RedirectToAction("Index");
}
catch (Exception ex)
{
var msg = ex.Message;
return RedirectToAction("Index");
// return View();
}
}
// GET: Usuarios/Delete/5
public ActionResult Delete(int id)
{
return View();
}
// POST: Usuarios/Delete/5
[HttpPost]
public ActionResult Delete(int id, FormCollection collection)
{
try
{
// TODO: Add delete logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
19. Ponga como inicial el proyecto web cliente compile la aplicación y pruébelo.