jCryption ASP.Net MVC - asp.net

Our security team asked me to not submit plain text passwords in my log in page, we use HTTPS though. so I thought that I need to do client side encryption before submit, I searched for solution and decided to implement jCryption.
However the example presented there is PHP/python, after a few google found this. I did whatever was explained in the link but I don't know how to retrieve form data that user submitted in form.
I only see a key returns in my login post back action and the LoginModel that should contain username, password is null.
Login.cshtml
#model Portal.Model.Membership.LoginModel
#using jCryption
#{
Layout = null;
jCryption.HandleRequest(Request);
}
<html>
<head>
<script src="~/Assets/global/plugins/jquery.min.js" type="text/javascript"></script>
<script src="~/Assets/global/plugins/jquery-migrate.min.js" type="text/javascript"></script>
#jCryption.RenderScriptFor("form", src: #Url.Content("~/Assets/admin/scripts/jquery.jcryption.3.1.0.js"))
</head>
<body>
#using (Html.BeginForm(null, null, FormMethod.Post, new { #autocomplete = "off" }))
{
<div class="form-body">
<div class="form-group">
#Html.LabelFor(x => x.Username, new { #class = "placeholder" })
#Html.TextBoxFor(x => x.Username, new { #class = "form-input", autocomplete = "off" })
<span></span>
</div>
<div class="form-group">
#Html.LabelFor(x => x.Password, new { #class = "placeholder" })
#Html.PasswordFor(x => x.Password, new { #class = "form-input", autocomplete = "off" })
<span></span>
</div>
</div>
<div class="form-group">
<button id="btnLogin">Login</button>
</div>
}
</body>
<!-- END BODY -->
</html>
Update
I put break point on login post action and it popup twice, one with key and another with jCryption:

For MVC 5, you need to adjust a little bit.
at login.cshtml
#using jCryption
#{
jCryption.HandleRequest(Request);
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
<script src="/Scripts/jquery.jcryption.3.1.0.mod.js"></script>
<script type="text/javascript">
// tweak for compatibility with jquery.validate
(function($){
var _jCryption = $.jCryption;
var jCryptionMod = function(el,options){
var form = $(el), hasValidator = !!form.data('validator');
if (hasValidator){
var v = form.validate();
var prev_handler = v.settings.submitHandler;
v.settings.submitHandler = function (_form, event) {
if( prev_handler ) prev_handler.apply(this, arguments);
var form = $(_form);
if (!form.hasClass('jc-before-submit')) {
v.settings.submitHandler = prev_handler;
form.addClass('jc-before-submit');
setTimeout( function(){ form.trigger('_jc_submit', event); }, 100 );
}
};
_jCryption.call(this, form, $.extend(options, {
submitElement: form,
submitEvent: '_jc_submit',
beforeEncryption: function(){
form.removeAttr('disabled');// form element hack ( IE11 )
return true;
}
}));
} else {
return _jCryption.call(this,el,options);
}
}
$.extend(jCryptionMod, $.jCryption);
$.jCryption = jCryptionMod;
})(jQuery);
</script>
<script type="text/javascript">
$(document).ready(function(){
var form = $('form');
var url = form.attr('action') || '/Account/Login';
form.jCryption({
getKeysURL: url + '?getPublicKey=true',
handshakeURL: url + '?handshake=true'
});
});
</script>
}
AccountController, you should follow JakeJP's documentation (exact same code).
At IE F12 Developer Tools (Network-->go to detail view-->Request body), it showns &jCryptionKey= but not &UserName= and &Password=.

You lack the jCryptionHandler attribute in your action method. The attribute is responsible for handling the jCryption handshake and decryption.
[jCryptionHandler]
public ActionResult Login(LoginModel model)
{
return View();
}

Related

Fluent Validation: Changing control style on error

I'm using Fluent Validation in my ASP.NET MVC application. I need to change the CSS class of the control when there's an error. Please see my code below.
using FluentValidation;
using Hrms.Framework.Common;
using Hrms.Web.Models;
namespace Hrms.Web.InputValidators
{
public class AnnouncementValidator : AbstractValidator<AnnouncementModel>
{
public AnnouncementValidator()
{
RuleFor(a => a.Title).NotEmpty().WithMessage("Announcement Title is required");
RuleFor(a => a.Title).MaximumLength(50).WithMessage(string.Format("Announcement Title should be 50 characters or less", 50));
}
}
}
Here is the code I have in the view (HTML)
#model Hrms.Web.Models.AnnouncementModel
#{
Layout = "~/Views/Shared/_Application.cshtml";
}
#using (Ajax.BeginForm("Save", "Announcement", new AjaxOptions
{
HttpMethod = "POST",
OnFailure = "saveFailed",
OnSuccess = "saveSucc",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "result"
}))
{
#Html.AntiForgeryToken()
<div id="result"></div>
<label>#Resources.Organization.Announcement.Title</label>
#Html.TextBoxFor(m => m.Title, new { maxlength = #GlobalConstants.AnnouncementTitleMaxLength })
#Html.ValidationMessageFor(model => model.Title, null, new { #class = "errVal" })
<input type="submit" value="Save">
}
#section scripts {
<script type="text/javascript">
$(document).ready(function () {
$("#SendingDate").datepicker();
});
function saveSucc(m) {
$("#Title").val("");
$("#Body").val("");
$("#SendingDate").val("");
}
function saveFailed() {
alert("saveFailed");
}
</script>
}
Any help is highly appreciated
When I tried to edit this post, it showed an error saying that I cannot edit this post because it is mostly code, it asked me to add more details. And because there are no more details in my mind to add, I decided to add this text. I'm sorry...

Fill dependent drop down list by using json

I have two drop down list that second one fill by on-change of first one.
I using json for ,but it doesn't work. here is my code:
<div class="col-md-6">
#Html.LabelFor(model => model.Counterparts.First().Name, new {#class = "control-label"})
#Html.DropDownListFor(m => m.CounterpartId, new SelectList(Model.Counterparts, "Id", "Name"), "select", new {#id = "SelectDepartment", onchange = "getData();"})
</div>
<div class="col-md-6">
#Html.LabelFor(model => model.Accounts.First().Name, new { #class = "control-label" })
#Html.DropDownListFor(m => m.AccountId, new SelectList(Model.Accounts, "Id", "Name"), "select", new { #class = "form-control" })
</div>
<script type="text/javascript" language="javascript">
function getData() {
var e = document.getElementById("SelectDepartment");
var counterpartid = e.options[e.selectedIndex].value;
alert('/ProcessCounterpart/GetCounterpartAccounts/' + counterpartid.toString());
$.getJSON('/ProcessCounterpart/GetCounterpartAccounts/' + counterpartid.toString(), function (data) {
alert(data);
});
}
</script>
public JsonResult GetCounterpartAccounts(int id)
{
var accounts = _accountService.GetAllAccountByCounterpartId(id);
return Json(accounts,JsonRequestBehavior.AllowGet);
}
I would personally suggest to use a selectize plugin. It has onchange event that fires each time you change the drop down. You can also fill options via ajax call which is what are you looking for. Here is an example:
$("#countriesDropDown").selectize({
load: function(query, callback) {
$.get("api/getCountries").done(function (data) {
if(data !== '') { callback(data) })
.fail(function(xmlHttpRequest, textStatus, errorThrown) {});
},
onChange: function(value) { loadCitylistByCountry(value); }
});
var $citiesSelectize = $("#citiesDropDown").[0].selectize;
function loadCitylistByCountry(value) {
$citiesSelectize.load(function(callback) {
$.get("api/getCitiesByCountry?coutryId=" + value).done(function (data) {
if(data !== '') { callback(data) })
.fail(function(xmlHttpRequest, textStatus, errorThrown) {});
});
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="countriesDropDown" type="text" />
<input id="citiesDropDown" type="text" />
Please note that this is just an example. This code might not even work. This is to only show you how you can use it. You can go to their site there you will find a lot of examples as well as the api.
Hope this will help
I suggest that you research ways on how to implement Cascading DropdownLists in MVC. There are many articles online such as:
Easiest way to create a cascade dropdown in ASP.NET MVC 3 with C#
http://www.c-sharpcorner.com/UploadFile/4d9083/creating-simple-cascading-dropdownlist-in-mvc-4-using-razor/
I'd go the JQuery route though; as it is the easiest one. The idea here is to populate both dropdowns and then use JQuery to hide or disable the options in the Child dropdown (i.e., the second one) based on selection in the Parent (i.e., the first one).

Ajax multiple form not working

<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<div id="com-#Model.demot.DemotId">
#Html.Partial("_Comments", Model.demot.Comments)
</div>
#using (Html.BeginForm("AddComments", "Demot", new { DemotId = #Model.demot.DemotId}, FormMethod.Post, new { data_ajax = true, data_ajax_target = "com-" + #Model.demot.DemotId }))
{
#Html.AntiForgeryToken();
<div class="error-summary-centred">
#Html.ValidationSummary()
</div>
<div id="add">
<table id="albumedit-address-table">
<tr>
<td>#Html.TextBoxFor(o => o.comment, new { #class = "comment", placeholder = "Comment", value = "" })</td>
<td>#Html.ValidationMessageFor(o => o.comment)</td>
</tr>
</table>
</div>
}
</div>
</div>
<script>
$(function () {
$('form').on('submit', function (e) {
var $form = $(this);
var $target = $form.attr('data-ajax-target');
$.ajax({
url: $(this).attr("action"),
type: $(this).attr("method"),
data: $(this).serialize(),
success: function (result) {
var $newContent = $(result);
$($('#' + $target)).replaceWith($newContent);
$newContent.effect("highlight");
$form.each(function(){
this.reset();
});
}
});
e.preventDefault();
});
});
</script>
I have many form in one page. My script work but only one time, subsequent requests sent to the server but no longer works adding results.
I would like to add comments ajax method worked all the time.
Please, any help.
You can try create a function that receive a parameter or ID when create a event.
For Example:
<script>
$(function() {
$('form').on('submit', function(e) {
var $form = $(this) functionAJAX(form)
})
});
functionAJAX() { /*His Code here*/ }
</script>

Passing data attribute to TextBoxFor not working

I have the following code inside my ASP.NET MVC 4 razor view:
<div>
<span class="f">Old Tag</span>
#Html.TextBoxFor(model => model.olfTag, new { data_autocomplete_source = Url.Action("AutoComplete", "Home") })
#Html.ValidationMessageFor(model => model.olfTag)
</div>
But data_autocomplete_source with TextBoxFor will not work. Can anyone give me some advice?
The following javascript should add the jquery autocomplete components to your control (and any control with the data-autocomplete-source attribute).
$(function() {
var createAutoComplete = function() {
var $input = $(this);
var options = {
source: $input.attr("data-autocomplete-source")
};
$input.autocomplete(options);
};
$("input[data-autocomplete-source]").each(createAutoComplete);
});

Partial view render on button click

I have Index view:
#using System.Web.Mvc.Html
#model MsmqTestApp.Models.MsmqData
<!DOCTYPE html>
<html>
<head>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
<meta name="viewport" content="width=device-width" />
<title>MsmqTest</title>
</head>
<body>
<div>
<input type="submit" id="btnBuy" value="Buy" onclick="location.href='#Url.Action("BuyItem", "MsmqTest", new { area = "Msmq" })'" />
<input type="submit" id="btnSell" value="Sell" onclick="location.href='#Url.Action("SellItem", "MsmqTest", new { area = "Msmq" })'" />
</div>
<div id="msmqpartial">
#{Html.RenderPartial("Partial1", Model); }
</div>
</body>
</html>
and partial:
#using System.Web.Mvc.Html
#model MsmqTestApp.Models.MsmqData
<p>
Items to buy
#foreach (var item in Model.ItemsToBuy)
{
<tr>
<td>#Html.DisplayFor(model => item)
</td>
</tr>
}
</p>
<p>
<a>Items Selled</a>
#foreach (var item in Model.ItemsSelled)
{
<tr>
<td>#Html.DisplayFor(model => item)
</td>
</tr>
}
</p>
And controller:
public class MsmqTestController : Controller
{
public MsmqData data = new MsmqData();
public ActionResult Index()
{
return View(data);
}
public ActionResult BuyItem()
{
PushIntoQueue();
ViewBag.DataBuyCount = data.ItemsToBuy.Count;
return PartialView("Partial1",data);
}
}
How to do that when i Click one of button just partial view render, now controller wants to move me to BuyItem view ;/
The first thing to do is to reference jQuery. Right now you have referenced only jquery.unobtrusive-ajax.min.js but this script has dependency on jQuery, so don't forget to include as well before it:
<script src="#Url.Content("~/Scripts/jquery.jquery-1.5.1.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
Now to your question: you should use submit buttons with an HTML form. In your example you don't have a form so it would be semantically more correct to use a normal button:
<input type="button" value="Buy" data-url="#Url.Action("BuyItem", "MsmqTest", new { area = "Msmq" })" />
<input type="button" value="Sell" data-url="#Url.Action("SellItem", "MsmqTest", new { area = "Msmq" })" />
and then in a separate javascript file AJAXify those buttons by subscribing to the .click() event:
$(function() {
$(':button').click(function() {
$.ajax({
url: $(this).data('url'),
type: 'GET',
cache: false,
success: function(result) {
$('#msmqpartial').html(result);
}
});
return false;
});
});
or if you want to rely on the Microsoft unobtrusive framework you could use AJAX actionlinks:
#Ajax.ActionLink("Buy", "BuyItem", "MsmqTest", new { area = "Msmq" }, new AjaxOptions { UpdateTargetId = "msmqpartial" })
#Ajax.ActionLink("Sell", "SellItem", "MsmqTest", new { area = "Msmq" }, new AjaxOptions { UpdateTargetId = "msmqpartial" })
and if you want buttons instead of anchors you could use AJAX forms:
#using (Ajax.BeginForm("BuyItem", "MsmqTest", new { area = "Msmq" }, new AjaxOptions { UpdateTargetId = "msmqpartial" }))
{
<button type="submit">Buy</button>
}
#using (Ajax.BeginForm("SellItem", "MsmqTest", new { area = "Msmq" }, new AjaxOptions { UpdateTargetId = "msmqpartial" }))
{
<button type="submit">Sell</button>
}
From what I can see you have already included the jquery.unobtrusive-ajax.min.js script to your page and this should work.
Maybe not the solution you were looking for but, I would forget about partials and use Javascript to call the server to get the data required and then return the data to the client as JSON and use it to render the results to the page asynchronously.
The JavaScript function;
var MyName = (function () {
//PRIVATE FUNCTIONS
var renderHtml = function(data){
$.map(data, function (item) {
$("<td>" + item.whateveritisyoureturn + "</td>").appendTo("#msmqpartial");
});
};
//PUBLIC FUNCTIONS
var getData = function(val){
// call the server method to get some results.
$.ajax({ type: "POST",
url: "/mycontroller/myjsonaction",
dataType: "json",
data: { prop: val },
success: function (data) {
renderHtml();
},
error: function () {
},
complete: function () {
}
});
};
//EXPOSED PROPERTIES AND FUNCTIONS
return {
GetData : getData
};
})();
And on the Server....
public JsonResult myjsonaction(string prop)
{
var JsonResult;
// do whatever you need to do
return Json(JsonResult);
}
hope this helps....

Resources