Logging of Access control logs in VB .NET - asp.net-mvc

I'm new to VB .NET, I want to write a method that saves a new entry to the database every time someone tries to log in no matter if it is a successful or failed attempt.
Also I need to capture the IP address of the machine where the attempt is performed.
Any advice of where to start

I dont believe capturing ip can be done locally without a library for it, but if you dont mind an api call you can use ip-api.com
'Query location data
Dim Req As HttpWebRequest
Dim Ret As HttpWebResponse = Nothing
Dim SR As StreamReader
Req = DirectCast(WebRequest.Create("http://ip-api.com/json"), HttpWebRequest)
Ret = DirectCast(Req.GetResponse(), HttpWebResponse)
SR = New StreamReader(Ret.GetResponseStream())
Dim Raw As String = Nothing
Raw = SR.ReadToEnd()
Dim JavaScriptSerialization As New JavaScriptSerializer()
Dim ipdata_object As New IPData()
ipdata_object = JavaScriptSerialization.Deserialize(Raw, ipdata_object.GetType)
dim ip_address as string = ipdata_object.query.tostring()
IPData Class
'IP Data API Deserialization classes for http://ip-api.com/json API response
<Serializable>
Class IPData
Public asinfo As String
Public city As String
Public country As String
Public countryCode As String
Public isp As String
Public lat As String
Public lon As String
Public org As String
Public query As String
Public region As String
Public regionName As String
Public status As String
Public timezone As String
Public zip As String
End Class
As for logging, depending on what you want to use, Mysql, CSV, Flatfile, etc
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'SAVE FUNCTION
Dim LogString as String = "User " + Username + " Attempted to login from " + ip_address + " Successfully/Failed"
My.Computer.FileSystem.WriteAllText("C://testfile.txt", inputString, True)
End Sub

You can try something like this for mysql database
Imports MySql.Data.MySqlClient
Imports System.Data.Sql
Imports System
Imports System.Data
Public Class LoginForm
'These variables store information regarding the sql connection string, and the sql class callers.
Dim connectionString As String = "Server=localhost; User Id=admin; Password=pass; Database=access_logs"
Dim SQLConnection As MySqlConnection = New MySqlConnection
Private Sub LoginButton_Click(sender As Object, e As EventArgs) Handles LoginButton.Click
Dim username As String = "usernametextbox.text"
Dim ip_address As String = ipfetchfunction()
Dim status As String = Nothing
If username.ToString() = "valid" And Password.ToString() = "valid" Then
status = "authorized"
Else
status = "failed"
End If
LogAttempt(username, ip_address, status)
End Sub
Public Function LogAttempt(user_name As String, ip_address As String, login_status As String) As Boolean
SQLConnection = New MySqlConnection()
SQLConnection.ConnectionString = connectionString
Dim sqlCommand As New MySqlCommand
Dim str_logSql As String
Try
str_logSql = "insert into access_log (username, user_ip, login_status) values ('" + user_name + "','" + ip_address + "','" + login_status + "')"
'MsgBox(str_logSql) uncomment for debugging
sqlCommand.Connection = SQLConnection
sqlCommand.CommandText = str_logSql
sqlCommand.ExecuteNonQuery()
Return True
Catch ex As Exception
Return False
'MessageBox.Show(ex.ToString()) Uncomment for debugging
End Try
End Function
End Class

Related

Sending Mail in vb.net

Imports System.Net
Imports System.Net.Mail
Public Class forgetpass
Inherits System.Web.UI.Page
Dim randomCode As String
Public Shared toUser As String
Private Sub btnsend_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnsend.Click
Dim from, pass, messageBody As String
Dim rand As Random = New Random()
randomCode = (rand.Next(999999)).ToString()
Dim message As MailMessage = New MailMessage
toUser = txtMail.Text
from = "Mymail#gmail.com"
pass = "MyPassword"
messageBody = "Your reset code is " + randomCode
message.To.Add(toUser)
message.From = New MailAddress(from)
message.Body = messageBody
message.Subject = "Password Resetting Code"
Dim smpt As SmtpClient = New SmtpClient("smpt.gmail.com")
smpt.EnableSsl = True
smpt.Port = 587
smpt.DeliveryMethod = SmtpDeliveryMethod.Network
smpt.Credentials = New NetworkCredential(from, pass)
Try
smpt.Send(message)
MsgBox("Check the email and enter the code")
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
End Class
This is my code to provide a random 6 digit code for resetting the password.
But the problem is while running the exception occurs that's shown below.
Exception
So anybody have an idea about that

How To Query Cosmos DB Collection From C#

getting the below error while connecting to cosmosdb from C#.
The input authorization token can't serve the request. Please check that the expected payload is built as per the protocol, and check the key being used. Server used the following payload to sign:
'get
wed, 07 aug 2019 13:20:12 gmt
ActivityId: 01489e82-0586-44d0-878d-0cc8cee22852, Microsoft.Azure.Documents.Common/2.5.1, Windows/10.0.15063 documentdb-netcore-sdk/2.4.0
using Microsoft.Azure.Documents.Client;
using System;
using System.Linq;
namespace DeviceCount
{
class Program
{
private static readonly string EndpointUri = "aaaa";
private static readonly string PrimaryKey = "bbb";
private static readonly string DBName = "ccc";
static void Main(string[] args)
{
DateTime currentTime = DateTime.Now;
var currentEpochTime = (int)currentTime.Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
var currentTimeMinusOneH = DateTime.Now.AddHours(-1);
var currentEpochTimeMinusOneH = (int)currentTimeMinusOneH.Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
ConnectionPolicy connectionPolicy = new ConnectionPolicy();
connectionPolicy.ConnectionMode = ConnectionMode.Gateway;
using (var client = new DocumentClient(new Uri(EndpointUri), PrimaryKey, connectionPolicy))
{
client.OpenAsync().Wait();
var response = client.CreateDocumentQuery
(UriFactory.CreateDocumentCollectionUri(DBName, "ddddd"),
"SELECT value count(c.id) FROM ddddd c where c._ts between " + currentEpochTime + " and " + currentEpochTimeMinusOneH).ToList();
var document = response.First();
Console.WriteLine($"Id:{document.id}");
Console.ReadLine();
}
}
}
}
Seems issue is in the token as per the error you need a valid signature hash for the master token in the authorization header to perform REST calls against Cosmosdb.
The signature hash is composed of the REST verb, resource type, resource id and the UTC DateTime of the operation. You will need to construct a new signature hash for every operation.

CloudTable.ExecuteQuery().ToList() is hanging

I am using Azure cosmos DB table.
In the following code, call to result.ToList() hangs.
I have tried several options such as TCP and HTTP.
However, if I make MVC controller async and use async query then everything works.
But as this is an old application, I cannot change all controllers and corresponding calls to async
private static string GetFinalFilter(Guid section, string page, string property, string lang)
{
string partitionKeyFilter = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, GetPartitionKey(page));
string sectionFilter = TableQuery.GenerateFilterConditionForGuid("Section", QueryComparisons.Equal, section);
string pageFilter = TableQuery.GenerateFilterCondition("Page", QueryComparisons.Equal, page);
string propertyFilter = TableQuery.GenerateFilterCondition("Property", QueryComparisons.Equal, property);
string languageFilter = TableQuery.GenerateFilterCondition("Language", QueryComparisons.Equal, lang);
string finalFilter = TableQuery.CombineFilters(TableQuery.CombineFilters(partitionKeyFilter, TableOperators.And, sectionFilter), TableOperators.And,
TableQuery.CombineFilters(pageFilter, TableOperators.And, TableQuery.CombineFilters(propertyFilter, TableOperators.And, languageFilter)));
return finalFilter;
}
private static string ProductIsNotDefinedSectionIsNotDefined(string page, string property, string lang, string defaultLang)
{
string finalFilter = GetFinalFilter(Guid.Empty, page, property, lang);
TableQuery<MDEntity> tableQuery = new TableQuery<MDEntity>().Where(finalFilter);
var result = mdTable.ExecuteQuery<MDEntity>(tableQuery);
var list = result.ToList();
it is very dangerous to go from async -->Sync --> async and it will give you deadlocks.
What you can do is on the async Executioncall to Cosmos write, .GetAwaiter().GetResult(), then you force it to actually return the result.

iTextSharp MVC View to PDF

I'm having a little trouble with my TextReader when trying to parse the html string I want to convert to PDF when using iTextSharp.
Function ViewDeliveryNote(ByVal id As Integer) As FileStreamResult
'Memory buffer
Dim ms As MemoryStream = New MemoryStream()
'the document
Dim document As Document = New Document(PageSize.A4)
'the pdf writer
PdfWriter.GetInstance(document, ms)
Dim wc As WebClient = New WebClient
Dim htmlText As String = wc.DownloadString("http://localhost:59800/Warehouse/DeliveryNote/" & id) 'Change to live URL
Dim worker As html.simpleparser.HTMLWorker = New html.simpleparser.HTMLWorker(document)
Dim reader As TextReader = New StringReader(htmlText)
document.Open()
worker.Open()
worker.StartDocument()
worker.Parse(reader)
worker.EndDocument()
worker.Close()
document.Close()
'ready the file stream
Response.ContentType = "application/pdf"
Response.AddHeader("content-disposition", "attachment;filename=DeliveryNote.pdf")
Response.Buffer = True
Response.Clear()
Response.OutputStream.Write(ms.GetBuffer(), 0, ms.GetBuffer.Length)
Response.OutputStream.Flush()
Response.End()
Return New FileStreamResult(Response.OutputStream, "application/pdf")
End Function
The line it stops on is worker.Parse(reader) with the error Object reference not set to an instance of an object even though StringReader(htmlText) has successfully read the HTML page.
I'm not sure what I'm doing wrong or what I'm missing at the moment so I would be grateful for any assistance.
UPDATE I just tried Dim reader As New StringReader(htmlText) instead but to no avail. Although htmlText still definitely contains a value, but the object thinks that it doesn't.
I would definitely write a custom action result for this to avoid polluting my controller. Also all those undisposed disposable resources in your code should be taken care of:
Public Class PdfResult
Inherits ActionResult
Private ReadOnly _id As Integer
Public Sub New(ByVal id As Integer)
_id = id
End Sub
Public Overrides Sub ExecuteResult(context As ControllerContext)
If context Is Nothing Then
Throw New ArgumentNullException("context")
End If
Dim response = context.HttpContext.Response
response.Buffer = True
response.ContentType = "application/pdf"
response.AddHeader("Content-Disposition", "attachment; filename=DeliveryNote.pdf")
Using client = New WebClient()
Dim htmlText As String = client.DownloadString("http://localhost:59800/Warehouse/DeliveryNote/" & _id) 'Change to live URL
Dim doc = New Document(PageSize.A4)
PdfWriter.GetInstance(doc, response.OutputStream)
Dim worker = New HTMLWorker(doc)
doc.Open()
worker.Open()
Using reader = New StringReader(htmlText)
worker.Parse(reader)
End Using
doc.Close()
End Using
End Sub
End Class
and then simply:
Function ViewDeliveryNote(ByVal id As Integer) As ActionResult
Return New PdfResult(id)
End Function
You should also make sure that the server has access to the desired url. Don't forget that his request will execute in the context of the Network Account which might not have the same privileges as normal accounts.

Can I get an Action's return type from an Action Filter?

I have an ASP.NET MVC 2 application in which I am creating a custom action filter. This filter sits on the controllers in the application and verifies from the database whether that function is currently available.
Public Overrides Sub OnActionExecuting(ByVal filterContext As System.Web.Mvc.ActionExecutingContext)
Try
' Check controller name against database.
Dim controllerName = filterContext.Controller.GetType().Name
controllerName = controllerName.Remove(controllerName.Length - 10)
' Look up availability.
Dim available As Boolean = _coreService.GetControllerAvailability(controllerName)
If Not available Then
' Redirect to unavailable notice.
filterContext.Result = New RedirectResult("/Home/Unavailable/")
End If
Catch ex As Exception
_eventLogger.LogWarning(ex, EventLogEntryType.Error)
Throw
End Try
End Sub
My problem is that depending on the action that has been requested I need to redirect the user to an action that returns either a view, partial views or JSON.
Given the ActionExecutingContext can I find out what the return type of the originally requested action is?
EDIT:
Ok, I'm getting closer but have another problem.
Public Overrides Sub OnActionExecuting(ByVal filterContext As System.Web.Mvc.ActionExecutingContext)
Try
' Check controller name against database.
Dim controllerName = filterContext.Controller.GetType().Name
Dim shortName = controllerName.Remove(controllerName.Length - 10)
' Look up availability.
Dim available As Boolean = _coreService.GetControllerAvailability(shortName)
If Not available Then
' find out what type is expected to be returned
Dim actionName As String = filterContext.ActionDescriptor.ActionName
Dim controllerType = Type.GetType("Attenda.Stargate.Web." & controllerName)
Dim actionMethodInfo = controllerType.GetMethod(actionName)
Dim actionReturnType = actionMethodInfo.ReturnType.Name
Select Case actionReturnType
Case "PartialViewResult"
filterContext.Result = New RedirectResult("/Home/UnavailablePartial/")
Case "JsonResult"
filterContext.Result = New RedirectResult("/Home/UnavailableJson/")
Case Else
filterContext.Result = New RedirectResult("/Home/Unavailable/")
End Select
End If
Catch ex As Exception
_eventLogger.LogWarning(ex, EventLogEntryType.Error)
Throw
End Try
End Sub
I can use reflection to find the return type of the action method. My problem is if I have the following methods on a controller:
Public Function Create() As ViewResult
Return View()
End Function
<AcceptVerbs(HttpVerbs.Post)>
Public Function Create(values as FormCollection) As ViewResult
' Do stuff here
End Function
I get an AmbiguousMatchException thrown.
With the information I have in the OnActionExecuting method, is there anyway of being more precise with determining the overload that is being called?
I created an AuthenticationFilterAttribute based on this which returns different results based on type:
/// <summary>
/// Access to the action will be blocked if the user is not logged in.
/// Apply this to the controller level or individual actions as an attribute.
/// </summary>
public class AuthenticationFilterAttribute : ActionFilterAttribute
{
protected const string InvalidAccess = "Invalid access";
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Find out if the user is logged in:
Controller controller = (Controller)filterContext.Controller;
if (!controller.User.Identity.IsAuthenticated)
{
switch (GetExpectedReturnType(filterContext).Name)
{
case "JsonResult":
var jsonResult = new JsonResult();
jsonResult.Data = new { Error = true, ErrorMessage = InvalidAccess };
jsonResult.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
filterContext.Result = jsonResult;
break;
// Assume same behaviour as ActionResult
default:
var actionResult = new ContentResult();
actionResult.Content = InvalidAccess;
filterContext.Result = actionResult;
break;
}
}
}
private Type GetExpectedReturnType(ActionExecutingContext filterContext)
{
// Find out what type is expected to be returned
string actionName = filterContext.ActionDescriptor.ActionName;
Type controllerType = filterContext.Controller.GetType();
MethodInfo actionMethodInfo = default(MethodInfo);
try
{
actionMethodInfo = controllerType.GetMethod(actionName);
}
catch (AmbiguousMatchException ex)
{
// Try to find a match using the parameters passed through
var actionParams = filterContext.ActionParameters;
List<Type> paramTypes = new List<Type>();
foreach (var p in actionParams)
{
paramTypes.Add(p.Value.GetType());
}
actionMethodInfo = controllerType.GetMethod(actionName, paramTypes.ToArray());
}
return actionMethodInfo.ReturnType;
}
}
Ok, this is the solution I have come up with.
Public Overrides Sub OnActionExecuting(ByVal filterContext As System.Web.Mvc.ActionExecutingContext)
Try
' Check controller name against database.
Dim controllerName = filterContext.Controller.GetType().Name
Dim shortName = controllerName.Remove(controllerName.Length - 10)
' Look up availability.
Dim available As Boolean = _coreService.GetControllerAvailability(shortName)
If Not available Then
' find out what type is expected to be returned
Dim actionName As String = filterContext.ActionDescriptor.ActionName
Dim controllerType = Type.GetType("Attenda.Stargate.Web." & controllerName)
Dim actionMethodInfo As MethodInfo
Try
actionMethodInfo = controllerType.GetMethod(actionName)
Catch ex As AmbiguousMatchException
' Try to find a match using the parameters passed through
Dim actionParams = filterContext.ActionParameters
Dim paramTypes As New List(Of Type)
For Each p In actionParams
paramTypes.Add(p.Value.GetType())
Next
actionMethodInfo = controllerType.GetMethod(actionName, paramTypes.ToArray)
End Try
Dim actionReturnType = actionMethodInfo.ReturnType.Name
Select Case actionReturnType
Case "PartialViewResult"
filterContext.Result = New RedirectResult("/Home/UnavailablePartial/")
Case "JsonResult"
filterContext.Result = New RedirectResult("/Home/UnavailableJson/")
Case Else
filterContext.Result = New RedirectResult("/Home/Unavailable/")
End Select
End If
Catch ex As Exception
_eventLogger.LogWarning(ex, EventLogEntryType.Error)
Throw
End Try
End Sub
If the Type.GetMethod(string) call fails to identify the method requested, I fetch the parameters collection from the ActionExecutingContext.ActionParameters collection and build an array of the types of the parameters passed in the request. I can then use the Type.GetMethod(string,type()) overload to be more specific about my request.
Some nice answers above, but in MVC Core, I notice you can just get to the method info by casting to a ControllerActionDescriptor, which would clean the above answers some. (I'm using this in a Blazor Webassembly Web Api backend in Preview 6)
((Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor)filterContext.ActionDescriptor).MethodInfo
So getting the Return type could become:
public static class FilterHelper
{
public static Type GetReturnType(this ActionExecutingContext filterContext)
{
return ((ControllerActionDescriptor)filterContext.ActionDescriptor).MethodInfo.ReturnType;
}
}
And be used like:
Type t = actionContext.GetReturnType();
Will update with an updated full solution for 6 Preview
By the time OnActionExecuting is invoked, the action method has not been executed yet, so there's no way you know whether that action method is going to return which subclass of ActionResult. So, unless you can go with CIL analysis implementation (which I think can get ugly very quickly), I don't think what you want to do is possible.
That said, isn't the fact that you redirect users to a view when the controller isn't available enough? I mean, I don't understand why you want to redirect users to a JSON result or a partial view.

Resources