I try to remove the Http header X-AspNetMvc-Version. I added this in Global.asax:
void Application_Start(object sender, EventArgs e)
{
MvcHandler.DisableMvcResponseHeader = true;
}
but it doesn't work. In Firefox I can see X-AspNetMvc-Version: "5.1".
What am I doing wrong?
You might need to just stick this into your Global.asax.cs:
MvcHandler.DisableMvcResponseHeader = true;
Check to see if you have anything configured in the HTTP response headers in IIS.
Related
I don't have a Spring Security implementation in my rest service, and I'm facing CORS 401 Unauthorized issue when trying to call resources in rest.
I red about it:
https://www.baeldung.com/spring-security-cors-preflight
https://docs.spring.io/spring-security/site/docs/5.0.7.RELEASE/reference/html5/#cors
I have 2 calls to rest:
1) Login
2) Others
The login functionality is based on Shiro, and when I perform login from Postman for example and then try to call other resource it works.
My problem starts when I started implementing a client side app with react and I'm trying to call the rest from fetch javascript method. I faced CORS issue when calling the login first and I solved it by adding #CorsOrigin annotation to my controller, but after login is succeeding the second call is still failing on cors 401.
If I correctly understand, CORS can be solved by adding filter t oWebSecurityConfig but if my app is working from Postman then there is no need to perform such a change in my server side app and I want to solve it from client side.
That leaves me with the option of passing the JSESSIONID in my requests, right?!
I still didn't figure out how to do it... where should I take the JSESSIONID from? I tried reading the cookies of the browser but didn't find it there... I tried taking it from Response headers of the first call to Login but the Response is coming empty!
Tried to solve it with Spring in server side but with no luck:
WebSecurityConfig:
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
// http
// .cors();
// .headers().disable();
// http
// .authorizeRequests()
// .requestMatchers(CorsUtils::isCorsRequest).permitAll()
// .anyRequest().authenticated()
// .and().httpBasic()
// .and().addFilterBefore(new WebSecurityCorsFilter(), ChannelProcessingFilter.class);
http.addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class);
}
}
WebSecurityCorsFilter:
public class WebSecurityCorsFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
res.setHeader("Access-Control-Max-Age", "3600");
res.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Accept, x-requested-with, Cache-Control");
chain.doFilter(request, res);
}
#Override
public void destroy() {
}
}
Or, CorsFilter (using on of them):
#Component
//#Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter{
public CorsFilter () {
super();
}
#Override
public final void doFilter(final ServletRequest req, final ServletResponse res, final FilterChain chain) throws IOException, ServletException {
final HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "http://localhost:3000");
// without this header jquery.ajax calls returns 401 even after successful login and SSESSIONID being succesfully stored.
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "X-Requested-With, Authorization, Origin, Content-Type, Version");
response.setHeader("Access-Control-Expose-Headers", "X-Requested-With, Authorization, Origin, Content-Type");
final HttpServletRequest request = (HttpServletRequest) req;
if (!request.getMethod().equals("OPTIONS")) {
chain.doFilter(req, res);
} else {
// do not continue with filter chain for options requests
}
}
#Override
public void destroy() {
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}
Thanks to this similar fetch issue: https://github.com/github/fetch/issues/386
I managed finally. So, to summarize:
1) No need for the Spring Security Config changes, except of Adding this annotation to controllers (you can add it just once to a base controller and all can inherit from it)
#CrossOrigin(origins = " * ", allowedHeaders = " * ")
2) From client side, when using fetch I had to use from both requests (Login and the second one):
credentials: 'include', //'same-origin'
(be attention that when using cors don't use the 'same-origin' value of credentials)
No need to set any cookies manually, the browser should handle it (If you need to write a Java client then it's needed... you can search for CookiesManagement java class and you'll find such implementation)
On Exceptions, what is the best way from the following to get the error in MVC?
protected void Application_Error(object sender, EventArgs e)
{
Exception ex0 = this.Context.Error;
Exception ex1 = httpContext.Error;
Exception ex2 = Server.GetLastError();
}
They return the same error.
Server.GetLastError() should be used in Application_Error() in global.asax
I am trying to make a redirect from my not www domain to my www domain like this:
protected void Application_BeginRequest(object sender, EventArgs e)
{
if (HttpContext.Current.Request.Url.ToString().Contains("http://mydomain.com"))
{
HttpContext.Current.Response.Status = "301 Moved Permanently";
HttpContext.Current.Response.AddHeader("Location", "http://www.mydomain.com");
}
}
For some reason the redirect is not done...(ok, I know this can be done by defining a CNAME also but I am simply wondering why this is not working...
I think it's something small buggy here...but I am not able to see it.
Use this tool to verify. May be you have to change code little as below,
protected void Application_BeginRequest(object sender, EventArgs e)
{
if (HttpContext.Current.Request.Url.ToString().Contains("http://mydomain.com"))
{
HttpContext.Current.Response.Status = "301 Moved Permanently";
HttpContext.Current.Response.AddHeader("Location",
Request.Url.ToString().ToLower().Replace(
"http://mydomain.com",
"http://www.mydomain.com"));
}
}
There is php page, let's call it http://www.aaaa.org/login.php which has two textboxes (name="username" and name="password") and a button.
And there is my .aspx page from which I want to login to that .php page. Once logged in I want to retrieve and parse some content of a subpage http://www.aaaa.org/details.php?id=1234.
I tried some code but it always retrieves the content of the login.php page so I assume I can't login at all.
Can you show me the exact code how to do this?
The language is C#.
To do this, you can use an HTTPClient library. Something like this:
http://www.codescales.com/
This will enable you to login and access the client application. Note that your application will be fragile and subjected to the web app and it's changes. So if they change the field names, your app will have to change as well. But it will work for what you are trying to achieve.
I would also suggest writing this as a separate library and not directly in your ASPX code.
protected void Page_Load(object sender, EventArgs e)
{
WebClient req = new WebClient();
CredentialCache myCache = new CredentialCache();
//myCache.Add(new Uri("http://www.aaaa.org/login.php"), "Basic", new NetworkCredential("login", "passw"));
myCache.Add(new Uri("http://www.aaaa.org/login.php"), "Digest", new NetworkCredential("login", "passw"));
req.Credentials = myCache;
string results;
results = System.Text.Encoding.UTF8.GetString(req.DownloadData("http://www.aaaa.org/login.php"));
}
protected void Button1_Click(object sender, EventArgs e)
{
string TheUrl = "http://www.aaaa.org/details.php?id=2923";
string response = GetHtmlPage(TheUrl);
TextBox2.Text = response;
}
---------------- updated: -----------------
protected void Page_Load(object sender, EventArgs e)
{
WebClient req = new WebClient();
CredentialCache myCache = new CredentialCache();
myCache.Add(new Uri("http://www.aaaa.org/login.php"), "Basic", new NetworkCredential("login", "passw"));
NameValueCollection postData = new NameValueCollection();
postData.Add("username", "login");
postData.Add("password", "passw");
req.UploadValues("http://www.aaaa.org/login.php", postData);
req.Credentials = myCache;
string results;
results = System.Text.Encoding.UTF8.GetString(req.DownloadData("http://www.aaaa.org/login.php"));
When I'm using a compression filter and get an error, the error page is just gibberish characters. The problem seems to be that when IIS transfers to the error page the compression filter is still in effect, but the headers are cleared. Without the "Content-encoding: gzip" header the browser just displays the raw gzipped binary data.
I'm using IIS7.5, ASP.NET MVC 2 Preview 2 and an ActionFilter that looks like this:
public class CompressResponseAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var request = filterContext.HttpContext.Request;
var response = filterContext.HttpContext.Response;
var acceptEncoding = request.Headers["Accept-Encoding"];
if (string.IsNullOrEmpty(acceptEncoding))
return;
acceptEncoding = acceptEncoding.ToLowerInvariant();
if (acceptEncoding.Contains("gzip"))
{
response.AppendHeader("Content-encoding", "gzip");
response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
}
else if (acceptEncoding.Contains("deflate"))
{
response.AppendHeader("Content-encoding", "deflate");
response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
}
}
}
Anyone else experienced this?
Update:
I stumbled upon Rick Strahl's blog post on this and other problems with compression. See here:
http://www.west-wind.com/weblog/posts/2011/May/02/ASPNET-GZip-Encoding-Caveats
His solution, which seems more reliable, is to put the following in Global.asax.cs:
protected void Application_Error(object sender, EventArgs e)
{
// Remove any special filtering especially GZip filtering
Response.Filter = null;
}
Original answer:
I fixed this by applying the compression in OnResultExecuting instead of OnActionExecuting.