Special char issue - json

I'm creating an .Net Core API but I have a problem I wanted to keep the '$' special char in the password.
I don't know why, when I execute my post method in the request URL it change it to %24
I try to change use Normalize but it didn't work...
Authentication Controller which is called by Employee controller :
public static class AuthenticationController
{
private class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private SafeTokenHandle() // called by P/Invoke
: base(true)
{
}
protected override bool ReleaseHandle()
{
return CloseHandle(this.handle);
}
}
private enum LogonType : uint
{
Network = 3, // LOGON32_LOGON_NETWORK
}
private enum LogonProvider : uint
{
WinNT50 = 3, // LOGON32_PROVIDER_WINNT50
}
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(IntPtr handle);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool LogonUser(
string userName, string domain, string password,
LogonType logonType, LogonProvider logonProvider,
out SafeTokenHandle token);
public static void AuthenticateUser(string userName, string password)
{
string domain = "domain";
string parts = domain + userName;
SafeTokenHandle token;
if (LogonUser(userName, domain, password, LogonType.Network, LogonProvider.WinNT50, out token))
token.Dispose();
else
throw new Win32Exception(); // calls Marshal.GetLastWin32Error()
}
}
Employee controller :
[Route("api/[controller]")]
[ApiController]
public class EmployeeController : Controller
{
private readonly intranetApplicationAPIContext _context;
public EmployeeController(intranetApplicationAPIContext context)
{
_context = context;
}
[HttpPost]
public ActionResult GetEmployee(string username , string password)
{
try
{
AuthenticationController.AuthenticateUser(username, password);
return Ok(username +"-"+ password);
}
catch (Win32Exception ex)
{
switch (ex.NativeErrorCode)
{
case 1326: // ERROR_LOGON_FAILURE (incorrect user name or password)
return BadRequest("Error code : "+ex.NativeErrorCode+" Incorrect username or password");
case 1327: // ERROR_ACCOUNT_RESTRICTION
return BadRequest("Error code : " + ex.NativeErrorCode + " Account restriction");
case 1330: // ERROR_PASSWORD_EXPIRED
return BadRequest("Error code : " + ex.NativeErrorCode + " Password expired");
case 1331: // ERROR_ACCOUNT_DISABLED
return BadRequest("Error code : " + ex.NativeErrorCode + " Account disabled");
case 1907: // ERROR_PASSWORD_MUST_CHANGE
return BadRequest("Error code : " + ex.NativeErrorCode + " Password must change");
case 1909: // ERROR_ACCOUNT_LOCKED_OUT
return BadRequest("Error code : " + ex.NativeErrorCode + " Account locked out");
default: // Other
return BadRequest("An error has occured");
;
}
}
}
}

Sending password or user private information in url is not recommmended.(Someone who listen the network can see request url and steal user password) You can send these informations in body of post request to dont encounter encoding problem and realizing process securely

Related

How to set JWT type in JWT Header

Not able to set the JWT token typ in token header.
This is for making secure API's which i have already developed in JAX-RS. Basically i have generating a token by Jwts.builder() method, and in return i am getting token in APPLICATION_JSON, ant i paste this token at https://jwt.io/ Debugger. So i got to know that there is no token type specified token header,there is only {
"alg": "HS512"
}
Maybe this could be a reason that i cannot access secured API's. When i try to access secured API's then i got "Signed Claims JWSs are not supported" exception.
AuthenticationService.java
private String issueToken(String login, String password) {
LocalDateTime now = LocalDateTime.now().plusMinutes(10L);
Instant instant = now.atZone(ZoneId.systemDefault()).toInstant();
Date jwtExpiry = Date.from(instant);
String jwtToken = Jwts.builder().setSubject(login).setIssuer("XYZ").setIssuedAt(new Date())
.setExpiration(jwtExpiry).signWith(SignatureAlgorithm.HS512, "secretKey").compact();
return jwtToken;
}
public class JWTTokenNeededFilter implements ContainerRequestFilter
{
public static final Logger logger = Logger.getLogger(JWTTokenNeededFilter.class);
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
String token = requestContext.getHeaderString("userToken");
if (token == null) {
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
}
try {
Jwts.parser().setSigningKey("secretKey").parseClaimsJwt(token);
logger.info("Valid Token " + token);
} catch (ExpiredJwtException expiredJwtException) {
logger.info("Token Expires " + expiredJwtException);
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
}
catch (Exception exception) {
logger.info("Exceptioin " + exception);
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
}
}
}
I am expecting token header like this
{
"alg": "HS512",
"typ": "JWT"
}
You can set the header just using the setHeaderParam("typ","JWT") jwt builder method.
https://github.com/jwtk/jjwt#header-parameters
String token = Jwts.builder()
.setHeaderParam("typ","JWT")
.setSubject(user.getUserId().toString())
.claim("Roles",authResult.getAuthorities())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis()+EXPIRATION_TIME))
.signWith(Keys.hmacShaKeyFor(key))
.compact();
You can set using header as explained here : https://github.com/jwtk/jjwt/issues/174
Header header = Jwts.header();
header.setType("JWT");
Then set header to builder (I haven't compiled the code)
private String issueToken(String login, String password) {
LocalDateTime now = LocalDateTime.now().plusMinutes(10L);
Instant instant = now.atZone(ZoneId.systemDefault()).toInstant();
Date jwtExpiry = Date.from(instant);
Header header = Jwts.header();
header.setType("JWT");
//set additional headers
String jwtToken =
Jwts.builder().setHeader((Map<String, Object>)
header).setSubject(login).setIssuer("XYZ").setIssuedAt(new
Date())
.setExpiration(jwtExpiry).signWith(SignatureAlgorithm.HS512,
"secretKey").compact();
return jwtToken;
}
you can use Header.JWT_TYPE static field in Header interface. This is more cleanable and avoid boilerplate code: For example:
private static String generateToken() {
return Jwts.builder()
.signWith(SignatureAlgorithm.HS256, secretKey)
.setHeaderParam("typ", Header.JWT_TYPE)
.compact();
}
and output which you want:
{
"typ": "JWT",
"alg": "HS256"
}

Get data array from sqlite database and post to API via json object... can be possible?

newbie here... i was developing app that send my data to api via retrofit. my code was working but it sends 1 data input only at the time.... in my case, i've like to do is I want to get more saved data in my sqlite (example 5 data saved) and send it all on api via json object.
This is my Activity:
DatabaseHelper databaseHelper2 = new
DatabaseHelper(getApplicationContext());
SQLiteDatabase db2 =
databaseHelper2.getWritableDatabase();
Cursor cursor =
databaseHelper2.retrieveSettingFromLocalDatabase(db2);
while (cursor.moveToNext()) {
ADDRESS =
cursor.getString(cursor.getColumnIndex(DatabaseHelper.SETTING_ADDRESS));
PORT =
cursor.getString(cursor.getColumnIndex(DatabaseHelper.SETTING_PORT));
TIMEINTERVAL=cursor.getString
(cursor.getColumnIndex(DatabaseHelper.SETTING_TIME_INTERVAL));
}
portInts=Integer.parseInt(PORT);
MapDetails mapDetails = new MapDetails(gg, lat, lon,
well, "0", portInts); //Datas ive get to send in api
List<MapDetails> data = new ArrayList<>();
data.add(mapDetails);
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("http://" + ADDRESS + ":" + PORT)
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
Api locate = retrofit.create(Api.class);
Call<MapDetails> call = locate.mapDetailLocation(data);
call.enqueue(new Callback<MapDetails>() {
#Override
public void onResponse(Call<MapDetails> call, Response<MapDetails> response) {
Snackbar.make(view, "" + response,
Snackbar.LENGTH_INDEFINITE)
.setAction("Action", null).show();
}
#Override
public void onFailure(Call call, Throwable t) {
Snackbar.make(view, "" + t.getMessage(),
Snackbar.LENGTH_INDEFINITE)
.setAction("Action", null).show();
}
});
This is my code in API:
public interface Api {
#POST("/api/Database/NewLocation")
Call<MapDetails> mapDetailLocation(#Body List<MapDetails> mapDetails)
}
This is my sample Client:
public class MapDetails {
#SerializedName("SerialNumber")
#Expose
private String SerialNumber;
#SerializedName("Coordinate1")
#Expose
private String Coordinate1;
#SerializedName("Coordinate2")
#Expose
private String Coordinate2;
#SerializedName("DateTime")
#Expose
private String DateTime;
#SerializedName("Speed")
#Expose
private String Speed;
#SerializedName("Port")
#Expose
private int Port;
public MapDetails(String serialNumber, String coordinate1, String
coordinate2, String dateTime, String speed, int port) {
SerialNumber = serialNumber;
Coordinate1 = coordinate1;
Coordinate2 = coordinate2;
DateTime = dateTime;
Speed = speed;
Port = port;
}
public String getSerialNumber() {
return SerialNumber;
}
public void setSerialNumber(String serialNumber) {
SerialNumber = serialNumber;
}
public String getCoordinate1() {
return Coordinate1;
}
public void setCoordinate1(String coordinate1) {
Coordinate1 = coordinate1;
}
public String getCoordinate2() {
return Coordinate2;
}
public void setCoordinate2(String coordinate2) {
Coordinate2 = coordinate2;
}
public String getDateTime() {
return DateTime;
}
public void setDateTime(String dateTime) {
DateTime = dateTime;
}
public String getSpeed() {
return Speed;
}
public void setSpeed(String speed) {
Speed = speed;
}
public int getPort() {
return Port;
}
public void setPort(int port) {
Port = port;
}
}
this is my sqlite database ive like to retrieve:
this is the sample posting ive created at the top
but in my case, ive like to do is this one, getting the saved data from my database and send it like this,:
The reason why only one is being sent is that you are sending outside of the while loop that traverses the Cursor, so only the last is sent.
That is you have :-
while (cursor.moveToNext()) {
ADDRESS = cursor.getString(cursor.getColumnIndex(DatabaseHelper.SETTING_ADDRESS));
PORT = cursor.getString(cursor.getColumnIndex(DatabaseHelper.SETTING_PORT));
TIMEINTERVAL=cursor.getString(cursor.getColumnIndex(DatabaseHelper.SETTING_TIME_INTERVAL));
}
So say the query extracted a Cursor with 10 rows as address 1,2,3....10 (for explantory purposes) then
The loop is entered ADDRESS is set to 1, the next iteration sets it to 2, the next to 3 ..... and finally ADDRESS is set to 10 (same for PORT and TIMEINTERVAL)
After the loop the data is sent so only one is sent (ADDRESS 10).
What you need is along the lines of :-
List<MapDetails> data = new ArrayList<>();
MapDetails mapDetails
Retrofit.Builder builder;
Retrofit retrofit;
Call<MapDetails> call;
Api locate;
while (cursor.moveToNext()) {
ADDRESS = cursor.getString(cursor.getColumnIndex(DatabaseHelper.SETTING_ADDRESS));
PORT = cursor.getString(cursor.getColumnIndex(DatabaseHelper.SETTING_PORT));
TIMEINTERVAL=cursor.getString(cursor.getColumnIndex(DatabaseHelper.SETTING_TIME_INTERVAL));
portInts=Integer.parseInt(PORT);
mapDetails = new MapDetails(gg, lat, lon, well, "0", portInts);
data.clear(); //<<<<<<<< remove previous entries if required????
data.add(mapDetails);
builder = new Retrofit.Builder()
.baseUrl("http://" + ADDRESS + ":" + PORT)
.addConverterFactory(GsonConverterFactory.create());
retrofit = builder.build();
locate = retrofit.create(Api.class);
call = locate.mapDetailLocation(data);
call.enqueue(new Callback<MapDetails>() {
#Override
public void onResponse(Call<MapDetails> call, Response<MapDetails> response) {
Snackbar.make(view, "" + response,
Snackbar.LENGTH_INDEFINITE).setAction("Action", null).show();
}
#Override
public void onFailure(Call call, Throwable t) {
Snackbar.make(view, "" + t.getMessage(),
Snackbar.LENGTH_INDEFINITE).setAction("Action", null).show();
}
}
Note the above is in-principle code. it has not been checked or tested and may therefore contain some errors.
It may be that you can send an entire set e.g. data with populated in which case you may only need up to data.add(mapDetails); in the loop and then have the following code outside the loop.
If I understood your question properly, you need to send JSONArray as payload for the request. But, you made a little mistake while preparing payload from SQLite database. #Mike T pointed out that mistake in his answer to your question.
Follow these codes to fix the problem.
DatabaseHelper databaseHelper2 = new DatabaseHelper(getApplicationContext());
SQLiteDatabase db2 = databaseHelper2.getWritableDatabase();
Cursor cursor = databaseHelper2.retrieveSettingFromLocalDatabase(db2);
List<MapDetails> data = new ArrayList<>(); // declare ArrayList outside and before while loop
while (cursor.moveToNext()) {
ADDRESS = cursor.getString(cursor.getColumnIndex(DatabaseHelper.SETTING_ADDRESS));
PORT = cursor.getString(cursor.getColumnIndex(DatabaseHelper.SETTING_PORT));
TIMEINTERVAL = cursor.getString(cursor.getColumnIndex(DatabaseHelper.SETTING_TIME_INTERVAL));
// pass arguments to MapDetails class constructor
portInts = Integer.parseInt(PORT);
MapDetails mapDetails = new MapDetails(gg, lat, lon, well, "0", portInts); //Datas ive get to send in api
// add prepared data to ArrayList
data.add(mapDetails);
}
// and finally execute network call
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("http://" + ADDRESS + ":" + PORT)
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
Api locate = retrofit.create(Api.class);
Call<MapDetails> call = locate.mapDetailLocation(data);
call.enqueue(new Callback<MapDetails>() {
#Override
public void onResponse(Call<MapDetails> call, Response<MapDetails> response) {
Snackbar.make(view, "" + response, Snackbar.LENGTH_INDEFINITE).setAction("Action", null).show();
}
#Override
public void onFailure(Call call, Throwable t) {
Snackbar.make(view, "" + t.getMessage(), Snackbar.LENGTH_INDEFINITE).setAction("Action", null).show();
}
});
PS: I'm not sure why are you taking ADDRESS and PORT from SQLite database. If they're same in every single row you don't need to take it from database right?

mock.method call returns null after stubbing

I am trying to test using Mockito
my class under test is
#Service
public class DynatraceAPIServiceImpl implements DynatraceAPIService {
private String apiUrl = "someurl";
private String apiToken = "sometoken";
#Override
public CreateCustomMetricResponse createCustomMetric(CreateCustomMetricRequest request) throws MonitoringException {
logger.info("Inside create custom metric");
if (request == null) {
logger.error("create metric request is null");
throw new MonitoringException("Create metric request is null");
}
String metricId = DynatraceConstants.METRIC_ID;
String displayName = request.getDisplayName();
CreateCustomMetricResponse response = httpUtils.postCustomMetric(apiUrl + "/v1/timeseries/" + metricId, apiToken, request);
if (response == null) {
logger.error("Error in creating custom metric with name : " + displayName);
throw new MonitoringException("Error in creating custom metric with name : " + displayName);
}
logger.info("Custom metric : " + displayName + " is created successfully.");
return response;
}
}
and my Test class is :
#RunWith(MockitoJUnitRunner.class)
public class DynatraceAPIServiceImplTest {
#InjectMocks
DynatraceAPIServiceImpl dynatraceAPIServiceImpl;
#Mock
DynatraceHttpUtils httpUtilsMock;
#Mock
DynatraceMonitoringUtils monitoringUtilsMock;
#Test(expected = MonitoringException.class)
public void createCustomMetricGetsNonNullResponse() throws MonitoringException {
CreateCustomMetricRequest mockRequest = CreateCustomMetricRequest.builder()
.displayName(DISPLAY_NAME)
.types(new String[] {"test-type"})
.build();
CreateCustomMetricResponse response = CreateCustomMetricResponse.builder()
.displayName(DISPLAY_NAME)
.types(new String[] {"test-type"})
.timeseriesId(TIMESERIES_ID)
.build();
boolean val = true;
when(monitoringUtilsMock.isValidMetricIdValue(anyString())).thenReturn(val);
when(httpUtilsMock.postCustomMetric(API_URL + "/v1/timeseries/" + METRIC_ID, API_TOKEN, mockRequest)).thenReturn(response);
CreateCustomMetricResponse actualRespnose = dynatraceAPIServiceImpl.createCustomMetric(mockRequest);
//verify(httpUtilsMock, times(1)).postCustomMetric(anyString(), anyString(), any(CreateCustomMetricRequest.class));
//assertEquals(actualRespnose.getDisplayName(), DISPLAY_NAME);
}
}
Here, when I execute the tests, it always end up having the response value to be null in line
CreateCustomMetricResponse response = httpUtils.postCustomMetric(apiUrl + "/v1/timeseries/" + metricId, apiToken, request);
Even if I have used when() statement to return response as I have created, it is returning null.
Really appreciate if someone can let me know what is wrong here. Thanks.
That normally happens when the params your production code uses differ from the ones that you stubbed the call with, an easy way to find out is to write the test like this
when(httpUtilsMock.postCustomMetric(any(), any(), any())).thenReturn(response);
CreateCustomMetricResponse actualRespnose = dynatraceAPIServiceImpl.createCustomMetric(mockRequest);
verify(httpUtilsMock).postCustomMetric(API_URL + "/v1/timeseries/" + METRIC_ID, API_TOKEN, mockRequest);
If you do that, you'll get a nicer error showing the difference between what your code did and what you verified it for
A better approach in general is to use 'strict stubs' so if your code does anything different to what you stubbed the mock for you'll get a nice error telling you what, where and why

How to send a success/failure message in json in web api?

How to send a success/failure response in json after execution of the webapi action?I have a function called FundTransfer, how to implement it like the output: given below
FundTransfer(string FromAccountNo, string ToAccountNo, decimal Amount,
string Remarks)
Output:
return: Success OR Fail with reason
string MsgCode: 00 (means success) OR 11 (means failure)
string Message: "Insufficient Balance ... or any other reason" (if fail,
there must be some reason in the Message")
At the moment when i call the api it executes and sends true on successfull execution
My Webapi Action (Now)
[HttpPost]
[ActionName("transfer")]
public IHttpActionResult FundTransfer([FromBody] FundTransfer transfer)
{
var transferData = BusinessLayer.Api.AccountHolderApi
.FundTransfer(transfer);
return Ok(transferData);
}
Business Layer
public static bool FundTransfer(FundTransfer transferData)
{
return
DatabaseLayer.Api.AccountHolderApi.FundTransfer(transferData);
}
DatabaseLayer
public static bool FundTransfer(FundTransfer transferData)
{
string sql = #"SELECT * FROM sms.post_fund_transfer('" +
transferData.FromAccount + "','" +
transferData.ToAccount + "','" + transferData.Amount +
"','" + transferData.Statement + "')";
using (var command = new NpgsqlCommand(sql))
{
return DBOperations.ExecuteNonQuery(command);
}
}
I am still learning webapi and did find some questions/answers related to response messages but couldnt get through.any help appreciated.
Thank You.
You could create a class which holds the response data type
public class responseMsg
{
public class MsgCode { get; set; }
public class Message { get; set; }
}
Then use that in your FundTransfer method
public responseMsg FundTransfer(string FromAccountNo, string ToAccountNo, decimal Amount, string Remarks)
{
//implement logic and create a response
return new responseMsg { MsgCode = "11", Message="Insufficient Balance ..." };
}
Then read the MsgCode in the api method and set the http response code
[HttpPost]
[ActionName("transfer")]
public IHttpActionResult FundTransfer([FromBody] FundTransfer transfer)
{
//call your logic which response with the responseMsg
var response = logic();
if(response.MsgCode == "11")
{
return Content(HttpStatusCode.BadRequest, response.Message);
}
else
{
return Ok(response.Message);
}
}

ConfirmBehavior dosen't support Ajax rendreing

After an Ajax update of a button with a ConfirmBehavior, all Confirm dialog attributes (Header, Message, Icon) becomes Null.
Its look like thoses values are evaluated during the buildView phase only (applyMetadata function)
In the getHeader()/getMessage()/getIcon() methods of the ConfirmBehavior there is no evaluation of expression.
How to get the real expression at this point ? (to evaluate it during the render phase)
Not a perfect solution
public class ConfirmBehavior extends ClientBehaviorBase {
private String header;
private String message;
private String icon;
#Override
public String getScript(ClientBehaviorContext behaviorContext) {
FacesContext context = behaviorContext.getFacesContext();
UIComponent component = behaviorContext.getComponent();
String source = component.getClientId(context);
if(component instanceof Confirmable) {
String headerExpr = (String) component.getAttributes().get("confirm_header");
if (headerExpr!=null)
this.header = (String) ContextUtil.eval(context, headerExpr);
String messageExpr = (String) component.getAttributes().get("confirm_message");
if (messageExpr!=null)
this.message = (String) ContextUtil.eval(context, messageExpr);
String iconExpr = (String) component.getAttributes().get("confirm_icon");
if (iconExpr!=null)
this.icon = (String) ContextUtil.eval(context, iconExpr);
String script = "PrimeFaces.confirm({source:'" + source + "',header:'" + getHeader() + "',message:'" + getMessage() + "',icon:'" + getIcon() + "'});return false;";
((Confirmable) component).setConfirmationScript(script);
return null;
}
else {
throw new FacesException("Component " + source + " is not a Confirmable. ConfirmBehavior can only be attached to components that implement org.primefaces.component.api.Confirmable interface");
}
}
...
}