Classic AJAX

AJAX stands for Asynchronous JavaScript And XML and has become an integral part of JavaScript coding. Implementing AJAX can often be simplified by using a JavaScript framework, like jQuery. Sometimes a framework is not available and you must use classic JavaScript. No need to worry, it is easily done using the code snippets below.


First define the Ajax HTTP request object.



function getHTTPObject()
{
var xmlhttp;
/*@cc_on
@if (@_jscript_version >= 5)
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (E) {
xmlhttp = false;
}
}
@else
xmlhttp = false;
@end @*/
if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
try {
xmlhttp = new XMLHttpRequest();
} catch (e) {
xmlhttp = false;
}
}
return xmlhttp;
}


An Ajax HTTP request can be made different ways, with GET and POST the most commonly used.


First create the Ajax request object and define a function to handle the response.

var ajax = getHTTPObject(); // See code snippet above
ajax.onreadystatechange=function()
{
/*
* Ready state:
* 0 = The request is not initialized
* 1 = The request has been set up
* 2 = The request has been sent
* 3 = The request is in process
* 4 = The request is complete
*/
if (ajax.readyState == 4) {
// Show response in alert box
alert('AJAX response = ' + ajax.responseText);
}
} // function

GET request:

// Open a connection to the server
/*
* param1 - Request method - GET or POST
* param2 - Server URL to send request
* param3 - Asynchronous connection (true for Ajax requests)
*/
ajax.open('GET', 'yoururl?yourparm1='+value1, true);
// Send the request
ajax.send(null);

POST request:

// Create a variable for the POST parameters
var params = 'parm1=value1&parm2=value2';
// Opening the server connection is the same, apart from the method parameter
ajax.open('POST', url, true);
//Send the proper header information along with the request
// Set the content type to text/html for pages without forms
// Pages with forms should have a content type of "application/x-www-form-urlencoded"
ajax.setRequestHeader("Content-type", "text/html");
ajax.setRequestHeader("Content-length", params.length);
ajax.setRequestHeader("Connection", "close");
// Send POST request
ajax.send(params);


If you need to access to the DOM (document object model) then use the responseXML property of the HTTP request object.
NOTE: The content type must be application/xml or text/xml for the responseXML property to be populated.



if (ajax.readyState == 4) {
// Show XML response in alert box
alert('AJAX response = ' + ajax.responseXML);
// Show "location" element value in alert box
alert(ajax.responseXML.documentElement.
getElementsByTagName("location")[0].firstChild.data);
}






Posted in JavaScript | Tagged | Leave a comment

How to verify your business Facebook Page

The reach of Facebook cannot be denied. With over 1.7 billion (with a “B”) monthly active users, it makes sense for your business to have a presence here. Assuming you have set up a Page for your business, a crucial step is to verify your business. Once verified, a check mark is shown on the Page and provides a level of authenticity to visitors. Facebook also claims it helps with search engine placement.

Below is a step-by-step guide to get your business Page verified.

Go to the business Page after logging in and click the Settings button at the upper right of the page.

Facebook Page verification

Facebook Page verification – step 1

Click the Page Verification option in the General settings.

Facebook Page verification

Facebook Page verification – step 2

Click the Verify this Page link.

Facebook Page verification

Facebook Page verification – step 3

A window will open with instructions on verification. Phone number verification is far simpler and is the method used here.

Facebook Page verification

Facebook Page verification – step 4

Ensure the business phone number is correct. An automated call will be initiated to the business phone number. Be prepared to write down a verification code. Click the Call Me Now button when ready.

Facebook Page verification

Facebook Page verification – step 5

Enter the verification code provided by the automated call in the space provided and click the Continue button.

Facebook Page verification

Facebook Page verification – step 6

That’s it! You now have a verified the Facebook Page for your business. When finsihed you will see a gray checkmark by the business name.

Facebook Page verified

Verified Facebook Page





Posted in Facebook | Tagged | Leave a comment

CSS Vertical Padding in a Span Element

If you have worked with CSS a fair amount then you are undoubtedly familiar with the span element. And if you have worked with the span element then you have likely scratched your head and possibly pulled out some hair trying to apply vertical margins or padding to it.

The fact is that span elements are inline elements. Content that is inserted after an inline element will continue on the same line whereas content following block elements will start on a new line. For this reason top and bottom padding cannot be added to a span element. Left and right padding can be added to a span element but top and bottom padding cannot be added without additional coding.

A CSS Trick

What do you do if you have a span element that needs top or bottom padding? The answer is to change its behavior to a block element. Add the display:block style to the span element that needs vertical padding and the top/bottom padding will work since the span element will now be treated as a block element.

Code Example

<style type="text/css">
.header { background-color:yellow; height:30px; }
.header span { display:block; font-weight:bold; padding-left:20px; padding-top:6px; }
</style>
...
<div class="header"><span style="">Shipment Information</span></div>

The header CSS class sets the element height at 30 pixels with a yellow background. The 2nd line in the style section tells the page to render any span element inside an element with the header class to render it as a block element. This allows the padding styles to take effect. Without the display:block style the padding would be ignored. See the code in action below.

Shipment Information





Posted in Web Development | Tagged | Leave a comment

Images in Sitemaps

This is not new information but bears repeating.

Most SEO professionals know about creating XML sitemaps for web sites so that search engines can more easily find and index content. One limitation of sitemaps is the ability only to include URLs in the map – until now. Google has created an extension to XML sitemaps that is used to provide additional information about important images that exist on each page in the sitemap. This may be useful for logos or other branded images. See the sitemap code example below.

<?xml version=”1.0″ encoding=”UTF-8″?>
<urlset xmlns=”http://www.sitemaps.org/schemas/sitemap/0.9″
xmlns:image=”http://www.google.com/schemas/sitemap-image/1.1″>
<url>
<loc>http://www.webtechnologyinc.com/contact.htm</loc>
<image:image>
<image:loc>http://www.webtechnologyinc.com/images/logo.jpg</image:loc>
</image:image>
</url>
</urlset>

More complete information is available on the Google blog.





Posted in Search Engine Optimization | Tagged , , | Leave a comment

Page Title Tag

The HTML page title tag describes the content of the page itself and is displayed at the top of the browser for all web site visitors. These are good reasons to always pay attention to the page title but the title also plays an important role in search engine optimization (SEO) strategies.

<title>This is the title of the page</title>
<meta name="description" content="This is an example of a meta description. This will normally show in search engine result pages (SERPs)." />
<meta name="keywords" content="meta, description, tag" />

Learn more about meta tags and the meta description tag in a prior post on this blog.

Creating a descriptive title tag is one of the most important organic SEO factors. The title tag is normally the fist thing that potential web site visitors see so it is important to convey your site’s content as well as entice the person to click on that link to your site.

Keywords

The presence and prominence of keywords in the title tag is a major factor for SEO. It is advantageous to have keywords appear early in the page title. This ensures the most important parts of the title are not cut off in the search engine result pages (SERPs) and also gives a more clear message about the site’s content.

Branding

Including a brand name in the title tag can be an effective SEO strategy if the brand is recognizable and gives the potential visitor a good idea of the web site’s content.

Length

Title tags displayed in SERPs are limited to 70 characters. There is no penalty for title tags longer than 70 characters but know that anything over 70 characters will be truncated when displayed in the SERPs.

Ideal Title Tag Format

As described in the factors above, the title tag ideally follows a specific pattern:

Primary Keyword – Secondary Keyword | Brand Name

NOTE – The dash and horizontal bar are interchangeable.





Posted in Search Engine Optimization | Tagged , | Leave a comment

Accept Terms and Conditions using jQuery Dialog

There may be a page on your web site that you want to protect by forcing visitors to read a disclaimer or accept terms and conditions before viewing the page contents. This is entirely possible with the jQuery JavaScript library along with jQuery UI, the user interface library that goes along with the jQuery core library.

The Page

The page contains the usual head and body sections. The interactivity of the page to make the web site visitor accept the terms and conditions is made possible by using the jQuery and jQueryUI JavaScript libraries.

Head section


<head>
<meta charset="utf-8">
<title>jQuery UI Dialog - Modal confirmation</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
<link type="text/css" rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css">
<script type="text/javascript" src="http://code.jquery.com/jquery-1.8.3.js"></script>
<script type="text/javascript" src="http://code.jquery.com/ui/1.8.2/jquery-ui.js"></script>
</head>

The jQuery and jQueryUI libraries are included in the head section, like any other external JavaScripr file reference. In this example the files are included from jquery.com. It is easy to download the jQuery and jQuery UI files and reference them locally.

Body Section


<body>

<div id="dialog-confirm" title="Terms and Conditions">
<p>Access to and use of this site is subject to the Terms and Conditions listed below.</p>
More legal-ese...
</div>

<div>
<p>
The content of the page goes here, just like any other page.
</p>
</div>

<script type="text/javascript">
$(document).ready(function() {
$( "#dialog-confirm" ).dialog({
buttons: {
"I agree": function() {
$( this ).dialog( "close" );
},
Cancel: function() {
window.location.replace("http://www.webtechnologyinc.com");
}
},
closeOnEscape: false,
draggable: false,
height: ($(window).height()) * 0.8,
modal: true,
open: function(event, ui) {
// Set opacity of parent window
$( ".ui-widget-overlay" ).css( "opacity", 0.90 );
// Hide close button on modal dialog
$( ".ui-dialog-titlebar-close" ).css( "display", 'none' );
},
resizable: false,
width: ($(window).width()) * 0.7
});
});
</script>

</body>

The body contains a section containing the text of the terms and conditions. This is what shows in the jQuery dialog box that is presented to web site visitors before they can view the page contents. The terms and conditions are contained in the following code snippet.


<div id="dialog-confirm" title="Terms and Conditions">
<p>Access to and use of this site is subject to the Terms and Conditions listed below.</p>
More legal-ese...
</div>

The dialog-confirm id on the opening div element uniquely identifies the element and its contents for the jQuery dialog to show when the page is loaded.

The title attribute on the div element is used by the jQuery dialog as the heading.

Lastly, in the JavaScript code at the bottom of the body section, note the id is used to assign behaviors to the div element associated with that id.
$( "#dialog-confirm" ).dialog

The buttons options contains all the buttons that will show in the popup dialog box.

All the other options (closeOnEscape, draggalbe, etc.) on the jQueryUI dialog widget can be found in the jQeuryUI dialog API doucmentation.





Posted in JavaScript, Web Development | Tagged , , | Leave a comment

Anatomy of a Search Engine

Most search engines have three parts: a crawler, an index, and a search interface. Let’s
look at each part individually to get a better understanding of them. Each part has its
own role to play in the process, with all parts working together to make searches
possible.

1. The Crawler

Also known as a “spider” or “bot”, this part of the search engine wanders the Web,
following links and picking up information for its database. Crawlers do most of their
work at times of the day when search engines are less busy, typically visiting frequently
updated pages more often. This is something to keep in mind when you are working on your
pages.

Your site’s title and content are the most important thing to a crawler. One of the best ways
to raise your site’s search engine ranking for specific key words is to implement them
into your title and your content.

2. The Index

Once the crawler has collected all that text, it is then stored and indexed. This allows
people searching for keywords and phrases to get results relating to what they were
searching for – their search results, displayed on search engine result pages (SERP). To see this in action, go to a search engine and enter a search phrase. You’ll see some text on
the page saying something like “results 1-10 of 1,234,000″. This means that the search
engine’s index contains 1,234,000 pages it believes are related to the search phrase entered.

In order to understand rating systems more thoroughly, consider your own site. When you
place links on your site you generally do so to increase the understanding of web site visitors on the content of your site.

If every site in a particular field of interest links to one specific site, this site is
probably very important to that field and should, therefore, be listed highly in the
lists of search engine results. This is the basic ideology of how Google and other search engines display SERPs.

3. The Interface

Search engines provide a public interface for users who want to find information on the
Web. They type the word or phrase they’re searching for, and the interface will run an
algorithm to find the pages relevant to their search and display them.

These algorithms are an important part of the SEO (Search Engine Optimization) business. You’ll notice when the algorithms change, the rankings of your web site may change. No two search engines have the same algorithms. They all work differently, with their unique features, and they will all rank your web site in their own way.





Posted in Google, Search Engine Optimization | Tagged , | Leave a comment

Spring Security

Before getting started we need to understand the basics of security.

What is security from an web application point of view?  Web security mainly comprises the following areas:  websites, web applications and web services.  Authentication is the verification of the credentials of the connection attempt. This process consists of sending the credentials from the remote access client to the remote access server in either a cleartext or encrypted form using an authentication protocol.  Authorization is the verification that the connection attempt is allowed. Authorization occurs after successful authentication.

What type of security threats are the above mentioned in web securities?  The vulnerabilities are varied amongst a collage of attacks and approaches, such as:

  1. Cross-site scripting
  2. SQL injection
  3. Denial of service attacks
  4. Buffer overload
  5. Code injection
  6. Memory corruption
  7. Cross Site Request Forgery (CSRF)

These are the most common attacks and things a developer should be prepared to understand and prevent in their code.

Another area of security provides access or no access to users based on the authority.  The user may have partial access to the application whereas another user may have complete access.

So we can assume that applications are secured by access control and also by preventing harmful code to exploit vulnerabilities.

There are many facets to security in general and can be viewed from various seats.  Our main focus since this is based on Spring Security is web application security.  In order to be fully security aware, the security person should analyze the security of the possible threats from various forms such as, network access, firewalls, software, and also human (social) interaction.

Now with a better understanding of what security is and what types of vulnerabilities exist, we can now dive into discussing Spring Security. As of this writing, we are using the Spring Security 4.0.0.M2 version and is what we will focus on.  In order to download and use the package that includes the security piece, you can easily do so by using Maven.

Within your pom.xml file you can use the following dependency to download jars needed for the security dependency:

<dependencies>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.0.0.M2.RELEASE</version>
</dependency>
</dependencies>

If you have worked with Spring, you are probably familiar with Maven.  If not, Maven is a tool used kind of like Ant, but it does all the work for you.  The only tricky part is the setup, which is fairly simple and straightforward and will not be discussed here.  You should familiarize yourself with it as it is commonly used on most projects.  By including the above dependency, pom.xml file, in your project, the application will pull down the latest version of the jars for you and will not be included until you build it.  So by defining the group id maven looks at it maven site for prerequisites and then determines the version you need and then it is pulled into the project.  So your pom.xml file will have other dependencies to pull down any other jars needed to build the project into a war.  Pretty cool huh?

Common Features Of Spring Security

  • Comprehensive and extensible support for both Authentication and Authorization
  • Protection against attacks like session fixation, clickjacking, cross site request forgery, etc
  • Servlet API integration
  • Optional integration with Spring Web MVC

Why use Spring Security?  Spring Security is a great way to implement security and enjoy the broad range of features that is offered by the packages.  As mentioned above the user can use various forms of attacks and vulnerabilities to exploit a web application.  Spring is package to handle those issues and most be specifically configured to prevent such vulnerabilities.  It is possible to view exploits for classroom affects to see the value in having security to prevent such acts.  There are other non Spring approaches to security but do not provide the added help to deal with vulnerabilities, so it is recommended to use Spring Security.

Java Configuration

Prior to Spring Security 3.2 the developer was required to use xml to configure Java Security.  There are similarities between version 3.1 and 3.2 within the Security Namespace Configuration.  The first step is to create a springSecurityFilterChain, which allows the application to process all requests filtering each request.

The following is an example of a basic easy approach to use:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.*;
import org.springframework.security.config.annotation.authentication.builders.*;
import org.springframework.security.config.annotation.web.configuration.*;

@Configuration
@EnableWebSecurity
publicclassSecurityConfigextendsWebSecurityConfigurerAdapter{

@Autowired

    publicvoid configureGlobal(AuthenticationManagerBuilder auth)throwsException {
          auth
            .inMemoryAuthentication()
                .withUser(“user”).password(“password”).roles(“USER”);
    }
}

The next thing to do is register  springSecurityFilterChain, and Spring has a base class to handle this.  AbstractSecurityWebApplicationInitializer is a base class that can handle the registration of the filter chain.

This approach only works if you are using Spring MVC.  The following code would be used to complete that task:

import org.springframework.security.web.context.*;

publicclassSecurityWebApplicationInitializer
      extends AbstractSecurityWebApplicationInitializer{}

Spring does offer an alternative if you are not using Spring MVC and must add the following constructor to the above class:

publicSecurityWebApplicationInitializer(){
      super(SecurityConfig.class);
}

Now that we have the basic wiring setup for URL processing, which provides all URLs be preprocessed by our filter chain. 

Next we need to ensure SecurityConfig is loaded by SecurityWebApplicationInitializer, by overriding getRootConfigClasses.

publicclassMvcWebApplicationInitializer
extends AbstractAnnotationConfigDispatcherServletInitializer{

@Override
protectedClass<?>[] getRootConfigClasses(){
       returnnewClass[]{
          SecurityConfig.class};
       } // … other overrides …
}

If we want to use form based authentication, we would setup the following code:

protectedvoid configure(HttpSecurity http)throwsException{
    http .authorizeRequests()
            .anyRequest().authenticated()
            .and().formLogin()
            .and().httpBasic();
}

The code example above is an implementation without having to use xml, but for some who are familiar with the xml approach may be more familiar with the following code:

<httpuse-expressions=”true”>
    <intercept-urlpattern=”/**”access=”authenticated”/>
    <form-login/>
    <http-basic/>
</http>

HTTP Basic authentication is the weakest for of authentication and is not usually used unless you have a simple application that security may not be that important.  An interesting point to spell out is Spring Security will implement a version of a login using the above actions.  No additional coding is required and a login form will be rendered to the user.  This is typical overriding with your own login page.

In order to create your own login, you can use something like this:

protectedvoid configure(HttpSecurity http)throwsException {

     http .authorizeRequests()
        .anyRequest()
        .authenticated()
        .and()
        .formLogin()
        .loginPage(“/login”)
        .permitAll();       
}

The login page would use something similar to this:

<c:urlvalue=”/login”var=”loginUrl”/>
<formaction=”${loginUrl}”method=”post”>
  <c:iftest=”${param.error != null}”>
     <p> Invalid username and password. </p>
  </c:if>

  <c:iftest=”${param.logout != null}”>
     <p> You have been logged out. </p>
  </c:if>
     <p><labelfor=”username”>Username</label>
        <inputtype=”text”id=”username”name=”username”/>
     </p>
     <p><labelfor=”password”>Password</label>
        <inputtype=”password”id=”password”name=”password”/>
     </p>
    <inputtype=”hidden”name=”${_csrf.parameterName}”              value=”${_csrf.token}”/>
    <buttontype=”submit”class=”btn”>Log in</button>
</form>

Using the following example, we can see you can customize actions accordingly:

protectedvoid configure(HttpSecurity http)throwsException{

    http .authorizeRequests() 
    .antMatchers(“/resources/**”, “/signup”, “/about”).permitAll()     
    .antMatchers(“/admin/**”).hasRole(“ADMIN”)
    .antMatchers(“/db/**”).access(“hasRole(‘ROLE_ADMIN’)
       and hasRole(‘ROLE_DBA’)”).anyRequest().authenticated()
    .and()

     // …

    .formLogin();
}

The code above is self explanatory but in case it is not clear to the reader we can elaborate the obvious.  As you can see the following urls /resources, /signup, and /about are allowing all users access and the ** in resources ensures anything with the url /resources and any other urls not defined.  This is good to use when many urls inclusions exist.  The /admin and /db urls are requiring authentication.

An in memory approach would look like this:

@Autowiredpublicvoid configureGlobal(AuthenticationManagerBuilder auth)throwsException{
    auth .inMemoryAuthentication()
            .withUser(“user”).password(“password”).roles(“USER”)
         .and().withUser(“admin”).password(“password”).roles(“USER”,”ADMIN”);
}

Hard coded values should not be used when ever possible.  This type of code requires code changes to update credentials and if you wanted to have multiple admin logins then you would have to create a chain of login and passwords in the code. 

If you want to use a JDBC approach:

@Autowired
privateDataSource dataSource;

@Autowiredpublicvoid configureGlobal(AuthenticationManagerBuilder auth)throwsException{

    auth .jdbcAuthentication()
            .dataSource(dataSource)
            .withDefaultSchema()
            .withUser(“user”).password(“password”).roles(“USER”).and()
            .withUser(“admin”).password(“password”).roles(“USER”,   “ADMIN”);

Here is an LDAP approach:

@Autowired
privateDataSource dataSource;

@Autowired
publicvoid configureGlobal(AuthenticationManagerBuilder auth)throwsException{
    auth .ldapAuthentication()
            .userDnPatterns(“uid={0},ou=people”)
            .groupSearchBase(“ou=groups”);
}

If there is a good reason to do so, you can also define multiple configurations to accomplish different authentications.

There are many ways to provide access restrictions to certain parts of the application.  Here is an example of a way to provide such constraints:

publicinterfaceBookService{
  @Secured(“IS_AUTHENTICATED_ANONYMOUSLY”)
  public Booking readBooking(Schedule schedule);
  @Secured(“IS_AUTHENTICATED_ANONYMOUSLY”)
  publicBooking[] findBookings();
  @Secured(“ROLE_DISPATCHER”)
  publicBooking post(Booking booking,Schedule schedule);
}

In order to use the above snippet you must define the following:

@Configuration@EnableGlobalMethodSecurity(securedEnabled =true)

publicclassMethodSecurityConfig{

   // …

}

Define the filter in web.xml:

<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
  <filter-name>springSecurityFilterChain</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

The above code illustrates how all url patterns will be processed by the springSecurityFilterChain.  The /* indicates all requests get processed or you could have another pattern if the filter should only apply in certain cases.

What is authentication?

Authentication is the ability to discriminate based on a way to ensure the person who’s login is verified by user name and password.  This only ensure the person who logs in properly knew the username/password, but does not guarantee it is the actual person who is authorized.  User context information is returned as used to have access to roles and other information about the user.  More then one form of authentication can be used to help to ensure the authorized person is using the system.  We can now use an access control mechanism across all application resources.

Here is a commandline example:

import org.springframework.security.authentication.*;
import org.springframework.security.core.*;
import org.springframework.security.core.authority.SimpleGrantedAuthority;import org.springframework.security.core.context.SecurityContextHolder;publicclassAuthenticationExample{

  privatestaticAuthenticationManager am =newSampleAuthenticationManager();

publicstaticvoid main(String[] args)throwsException{
    BufferedReader in =newBufferedReader(newInputStreamReader(System.in));
while(true){
      System.out.println(“Please enter your username:”);
      String name = in.readLine();
System.out.println(“Please enter your password:”);
      String password = in.readLine();try{Authentication request =newUsernamePasswordAuthenticationToken(name, password);
        Authentication result = am.authenticate(request);SecurityContextHolder.getContext().setAuthentication(result);break;
      }
      catch(AuthenticationException e){
        System.out.println(“Authentication failed: “+ e.getMessage());
      }
    }

    System.out.println(“Successfully authenticated. Security context contains: “+SecurityContextHolder.getContext().getAuthentication());
  }
}

classSampleAuthenticationManagerimplementsAuthenticationManager{
  staticfinalList<GrantedAuthority> AUTHORITIES =newArrayList<GrantedAuthority>();static{
    AUTHORITIES.add(newSimpleGrantedAuthority(“ROLE_USER”));
  }

  publicAuthentication authenticate(Authentication auth)throwsAuthenticationException{
    if(auth.getName().equals(auth.getCredentials())){
      returnnewUsernamePasswordAuthenticationToken(auth.getName(), auth.getCredentials(), AUTHORITIES);
    }thrownewBadCredentialsException(“Bad Credentials”);
  }
}

We have to this point of discussed username and passwords, and we have not discussed securing the data or making our data more secure.  A system that stores passwords should use password encoding and never should be in plain text.  Do not use a plain hash function and sha or md5 should be used.  A hash is used to change the value of a password and is then stored versus the plain text.  Hashing makes it harder for someone viewing the data to determine the actual password.  Hashing algorithms are basically a shortened version of the actual string and is often used for encryption algorithms.  A better approach to securing data would be to call an enterprise application, which performs this action.

Web Application Security

As the heading suggests we are focused on web application security which make use of HTTP and Servlet API. 

The easiest way to provide security via your application is to setup and use servlet filters.  Filters are very useful for many purposes but the main thing to remember is filters provide a robust approach to a systematic approach to handle all http requests and to be able to provide some functional control globally without having to do it in each class.  This provides the ability to create a SecurityFilter that is called each time a request is made on the server.  You can easily imagine that would be useful for security and other purposes.  Filters are added to the web.xml file and are mapped to a servlet already defined to handle requests. 

To use DelegatingFilterProxy, you will need to add something like this in the web.xml file:


<filter>
<filter-name>myFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</filter>

Now that you have setup the use of DelegatingFilterProxy you can create an instance using the following:


<bean id="filterChainProxy"class="org.springframework.security.web.FilterChainProxy">
<constructor-arg>
<list><sec:filter-chainpattern="/restful/**"filters="
           securityContextPersistenceFilterWithASCFalse,
           basicAuthenticationFilter,
           exceptionTranslationFilter,
           filterSecurityInterceptor"/>
<sec:filter-chainpattern="/**"filters="
           securityContextPersistenceFilterWithASCTrue,
           formLoginFilter,
           exceptionTranslationFilter,
           filterSecurityInterceptor"/>
</list>
</constructor-arg>
</bean>

Request Mapping & HttpFirewall

FilterChainProxy is responsible for deciding which requests get processed and FilterSecurityInterceptor decides which security constraints apply.  The servlet specification requires that the HttpServetRequest is accessible by specific getter method functions.  These are the contextPath, servletPath, pathInfo, and queryString.  Spring Securiity is only concerned with paths, so the contextPath is ignored.  The servlet specification does not clearly define where parameters are stored in the servletPath or pathInfo, so it varies from servlet container.  Security defined at the service layer is much better for handling security and should be used.
 

Filter Security Interceptor

FilterSecurityInterceptor is responsible for handling the security for HTTP resources.  The interceptor will require an AuthenticationManager and AccessDecisionManager be used to handle the control. 

Here is an example of a bean using the interceptor:

<beanid=”filterSecurityInterceptor”class=”org.springframework.security.web.access.intercept.FilterSecurityInterceptor”>
  <propertyname=”authenticationManager”ref=”authenticationManager”/>
  <propertyname=”accessDecisionManager”ref=”accessDecisionManager”/>
<propertyname=”securityMetadataSource”>
    <security:filter-security-metadata-source>
<security:intercept-urlpattern=”/secure/super/**”access=”ROLE_WE_DONT_HAVE”/><security:intercept-urlpattern=”/secure/**”access=”ROLE_SUPERVISOR,ROLE_TELLER”/></security:filter-security-metadata-source>
  </property>
</bean>
 

ExceptionTranslationFilter

As the name suggests,  this filter is used to handle any exceptions thrown with the FilterSecurityInterceptor and does not handle any security. 

Here are examples of beans that can be defined:

<beanid=”exceptionTranslationFilter”class=”org.springframework.security.web.access.ExceptionTranslationFilter”>
 <propertyname=”authenticationEntryPoint”ref=”authenticationEntryPoint”/>
 <propertyname=”accessDeniedHandler”ref=”accessDeniedHandler”/>
</bean>

<beanid=”authenticationEntryPoint”class=”org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint”>
<propertyname=”loginFormUrl”value=”/login.jsp”/>
</bean>

<beanid=”accessDeniedHandler”class=”org.springframework.security.web.access.AccessDeniedHandlerImpl”>
<propertyname=”errorPage”value=”/accessDenied.htm”/>
</bean>
 

AuthenticationEntryPoint

The AuthenticationEntryPoint will be called if the user requests a secure HTTP resource but they are not authenticated. An appropriate AuthenticationException or AccessDeniedException will be thrown by a security interceptor further down the call stack, triggering the commence method on the entry point. This does the job of presenting the appropriate response to the user so that authentication can begin. The one we’ve used here is LoginUrlAuthenticationEntryPoint, which redirects the request to a different URL (typically a login page). The actual implementation used will depend on the authentication mechanism you want to be used in your application.
 

AccessDeniedHandler

AccessDeniedHandler is called after a user has been authenticated but does not have permissions to a resource of which they have tried to access.  By default, an AccessDeniedHandlerImpl is used, which just sends a 403 (Forbidden) response to the client.
 

SecurityContextPersistenceFilter

As we saw previously, this filter has two main tasks. It is responsible for storage of the SecurityContext contents between HTTP requests and for clearing the SecurityContextHolder when a request is completed. Clearing the ThreadLocal in which the context is stored is essential, as it might otherwise be possible for a thread to be replaced into the servlet container’s thread pool, with the security context for a particular user still attached. This thread might then be used at a later stage, performing operations with the wrong credentials.

Here is a simple implementation of the class:

<beanid=”securityContextPersistenceFilter”class=”org.springframework.security.web.context.SecurityContextPersistenceFilter”/>
 

SecurityContextRepository

The following interface is used for loading and storing securityContext:

publicinterfaceSecurityContextRepository{
  SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder);
void saveContext(SecurityContext context,HttpServletRequest request,HttpServletResponse response);
}

Here is an example of a bean implementation:

<beanid=”securityContextPersistenceFilter”class=”org.springframework.security.web.context.SecurityContextPersistenceFilter”>
  <propertyname=’securityContextRepository’>
    <beanclass=’org.springframework.security.web.context.HttpSessionSecurityContextRepository’>
<propertyname=’allowSessionCreation’value=’false’/>
    </bean>
  </property>
</bean>
 

UsernamePasswordAuthenticationFilter

The login form simply contains j_username and j_password input fields, and posts to the URL that is monitored by the filter (by default this is /j_spring_security_check). The basic filter configuration looks something like this:

<beanid="authenticationFilter"class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<propertyname="authenticationManager"ref="authenticationManager"/>
</bean>

 

Application Flow on Authentication

The AuthenticationManager is responsible for handling authentication and will pass control to the AuthenticationSuccessHandler and AuthenticationFailureHandler accordingly.  So if a user were to login and if they are authenticated successfully, then they would be passed to the AuthenticationSuccessHandler , otherwise they would be passed to the AuthenticationFailureHandler for a failed attempt.
 

Servlet 3+ Integration

Spring integrates with the Servlet 3 specification by interfacing with the authenticate and login member functions.  The HttpServletRequest.authenticate will proceed to the application if successful authentication and will send the request back to the HttpServletRequest.login if it fails.   HttpServletRequest.logout is used to log the current user out of the application.  At this point, the HttpSession will be invalidated and typically a redirect to a welcome page or logout page.
 

AsyncContext.start(Runnable)

The AsyncContext.start(Runnable) method that ensures your credentials will be propagated to the new Thread. Using Spring Security’s concurrency support, Spring Security overrides the AsyncContext.start(Runnable) to ensure that the current SecurityContext is used when processing the Runnable. For example, the following would output the current user’s Authentication:

 
finalAsyncContext async = httpServletRequest.startAsync();
async.start(newRunnable(){publicvoid run(){
Authentication authentication =SecurityContextHolder.getContext().getAuthentication();
try{
           finalHttpServletResponse asyncResponse =(HttpServletResponse) async.getResponse();
            asyncResponse.setStatus(HttpServletResponse.SC_OK);
            asyncResponse.getWriter().write(String.valueOf(authentication));
            async.complete();
}catch(Exception e){
  thrownewRuntimeException(e);
}
}
});

 

Basic and Digest Authentication

Basic authentication is often used with web applications today especially with sites that are not done as an enterprise approach.  In most web applications quickly being done using simple web application generators are perfect for the small company and when limited exposure.  Basic authentication uses plain text to transport passwords and should not be used in most cases.  If it has to be used then you can ensure at a minimum to use SSL (HTTPS). 
 

BasicAuthenticationFilter

BasicAuthenticationFilter is responsible for processing basic authentication credentials presented in HTTP headers. This can be used for authenticating calls made by Spring remoting protocols (such as Hessian and Burlap), as well as normal browser user agents (such as Firefox and Internet Explorer). The standard governing HTTP Basic Authentication is defined by RFC 1945, Section 11, and BasicAuthenticationFilter conforms with this RFC. Basic Authentication is an attractive approach to authentication, because it is very widely deployed in user agents and implementation is extremely simple (it’s just a Base64 encoding of the username:password, specified in an HTTP header).
 

DigestAuthenticationFilter

DigestAuthenticationFilter is capable of processing digest authentication credentials presented in HTTP headers. Digest Authentication attempts to solve many of the weaknesses of Basic authentication, specifically by ensuring credentials are never sent in clear text across the wire. Many user agents support Digest Authentication, including FireFox and Internet Explorer. The standard governing HTTP Digest Authentication is defined by RFC 2617, which updates an earlier version of the Digest Authentication standard prescribed by RFC 2069. Most user agents implement RFC 2617. Spring Security’s DigestAuthenticationFilter is compatible with the “auth” quality of protection (qop) prescribed by RFC 2617, which also provides backward compatibility with RFC 2069. Digest Authentication is a more attractive option if you need to use unencrypted HTTP (i.e. no TLS/HTTPS) and wish to maximise security of the authentication process. Indeed Digest Authentication is a mandatory requirement for the WebDAV protocol, as noted by RFC 2518 Section 17.1.
 

 Cross Site Request Forgery (CSRF)

What is a cross site request forgery threat? 

Assume that your bank’s website provides a form that allows transferring money from the currently logged in user to another bank account. For example, the HTTP request might look like:

POST /transfer HTTP/1.1Host: bank.example.com
Cookie: JSESSIONID=randomid;Domain=bank.example.com;Secure;HttpOnlyContent-Type: application/x-www-form-urlencoded

amount=100.00&routingNumber=1234&account=9876
 
 

Now pretend you authenticate to your bank’s website and then, without logging out, visit an evil website. The evil website contains an HTML page with the following form:


<formaction="https://bank.example.com/transfer"method="post">     <inputtype="hidden"name="amount"value="100.00"/>
<inputtype="hidden"name="routingNumber"value="evilsRoutingNumber"/>
<inputtype="hidden"name="account"value="evilsAccountNumber"/><inputtype="submit"value="Win Money!"/>

</form>

We all like to win money, so you click on the submit button. In the process, you have unintentionally transferred $100 to a malicious user. This happens because, while the evil website cannot see your cookies, the cookies associated with your bank are still sent along with the request.

Worst yet, this whole process could have been automated using JavaScript. This means you didn’t even need to click on the button. So how do we protect ourselves from such attacks?

One solution is to use the Synchronizer Token Pattern. This solution is to ensure that each request requires, in addition to our session cookie, a randomly generated token as an HTTP parameter. When a request is submitted, the server must look up the expected value for the parameter and compare it against the actual value in the request. If the values do not match, the request should fail.

We can relax the expectations to only require the token for each HTTP request that updates state. This can be safely done since the same origin policy ensures the evil site cannot read the response. Additionally, we do not want to include the random token in HTTP GET as this can cause the tokens to be leaked.

Let’s take a look at how our example would change. Assume the randomly generated token is present in an HTTP parameter named _csrf. For example, the request to transfer money would look like this:

POST /transfer HTTP/1.1Host: bank.example.com
Cookie: JSESSIONID=randomid;Domain=bank.example.com;Secure;HttpOnlyContent-Type: application/x-www-form-urlencoded

amount=100.00&routingNumber=1234&account=9876&_csrf=<secure-random>

CSRF Caveats

Timeouts can occur and the token that is stored is no longer available in the session object.  In this case, a 403 would occur as access should be denied to that resource.  Using JavaScript the user can be notified that the session is about to expire and allow the user to extend the session without a timeout occurring. 

Logging in the token should be stored in the session object, so it can be used to determine that the user is actually making the request and not some random hacker.  Cookies should not store the token or it is possible for the hijacker to use the cookie to mask the user authenticity. 

Logging out the token is useful to prevent the user from being logged out of the application also.  So the threat can also be used to prevent a user from performing their work or continual interruption of work.

HiddenHttpMethodFilter

The HiddenHttpMethodFilter should be placed the Spring Security filter. In general this is true, but it could have additional implications when protecting against CSRF attacks.

Note that the HiddenHttpMethodFilter only overrides the HTTP method on a POST, so this is actually unlikely to cause any real problems. However, it is still best practice to ensure it is placed Spring Security’s filters.

Security Http Response Headers

Spring Security easily allows users to inject security headers to protect their applications.

Default Security Headers:

Cache Control

The no-cache directive in a response indicates that the response must not be used to serve a subsequent request i.e. the cache must not display a response that has this directive set in the header but must let the server serve the request. The no-cache directive can include some field names; in which case the response can be shown from the cache except for the field names specified which should be served from the server. The no-store directive applies to the entire message and indicates that the cache must not store any part of the response or any request that asked for it.

Content Type Options

The only defined value, “nosniff”, prevents Internet Explorer and Google Chrome from MIME-sniffing a response away from the declared content-type. This also applies to Google Chrome, when downloading extensions. This reduces exposure to drive-by download attacks and sites serving user uploaded content that, by clever naming, could be treated by MSIE as executable or dynamic HTML files.

HTTP Strict Transport Security

HTTP Strict-Transport-Security (HSTS) enforces secure (HTTP over SSL/TLS) connections to the server. This reduces impact of bugs in web applications leaking session data through cookies and external links and defends against Man-in-the-middle attacks. HSTS also disables the ability for user’s to ignore SSL negotiation warnings.

X-Frame-Options

Provides Clickjacking protection. Values: deny – no rendering within a frame, sameorigin – no rendering if origin mismatch, allow-from: DOMAIN – allow rendering if framed by frame loaded from DOMAIN

X-XXS-Options

This header enables the Cross-site scripting (XSS) filter built into most recent web browsers. It’s usually enabled by default anyway, so the role of this header is to re-enable the filter for this particular website if it was disabled by the user. This header is supported in IE 8+, and in Chrome (not sure which versions). The anti-XSS filter was added in Chrome 4. Its unknown if that version honored this header.

Example of usage:

<http><!– … –>
<headers>
        <cache-control/>
        <content-type-options/>
        <hsts/>
        <frame-options/>
        <xss-protection/>
</headers>
</http>

Custom Headers

The main reason to use custom headers is if a new threat were to arise and the standard is in the works.  Then you can create a customer header to handle such cases.

Session Management

HTTP session related functonality is handled by a combination of the SessionManagementFilter and the SessionAuthenticationStrategy interface, which the filter delegates to. Typical usage includes session-fixation protection attack prevention, detection of session timeouts and restrictions on how many sessions an authenticated user may have open concurrently.

Anonymous Authentication

It is normally a good idea to have a denial by default and allow and disallow user access across the application.  In the case of anonymous login, the user will have access to allowed pages and resources while maintaining security across protected pages.  There would be no difference between an anonymous user and an unauthenticated user. 

Here is a bean example for the anonymous user:

<beanid=”anonymousAuthFilter”class=”org.springframework.security.web.authentication.AnonymousAuthenticationFilter”>
<propertyname=”key”value=”foobar”/>
<propertyname=”userAttribute”value=”anonymousUser,ROLE_ANONYMOUS”/>
</bean>

<beanid=”anonymousAuthenticationProvider”class=”org.springframework.security.authentication.AnonymousAuthenticationProvider”>
  <propertyname=”key”value=”foobar”/>
</bean>

<beanid=”filterSecurityInterceptor”class=”org.springframework.security.web.access.intercept.FilterSecurityInterceptor”>
  <propertyname=”authenticationManager”ref=”authenticationManager”/>
  <propertyname=”accessDecisionManager”ref=”httpRequestAccessDecisionManager”/>
  <propertyname=”securityMetadata”>
    <security:filter-security-metadata-source><security:intercept-urlpattern=’/index.jsp’access=’ROLE_ANONYMOUS,ROLE_USER’/><security:intercept-urlpattern=’/hello.htm’access=’ROLE_ANONYMOUS,ROLE_USER’/><security:intercept-urlpattern=’/logoff.jsp’access=’ROLE_ANONYMOUS,ROLE_USER’/><security:intercept-urlpattern=’/login.jsp’access=’ROLE_ANONYMOUS,ROLE_USER’/><security:intercept-urlpattern=’/**’access=’ROLE_USER’/>
    </security:filter-security-metadata-source>
  </property>
</bean>

Authorization Architecture

All the authorization approaches use a GrantAuthority Object.  By returning a string representation of the object it is easy for it to be read by the AccessDecisionManager.  If it cannot be done then getAuthority() must return null.  If that happens then the AccessDecisionManager will have to support that feature.  Spring provides one approach to GrantAuthority which is GrantAuthorityImpl.  The authentication object will be populated with the information provided by the GrantAuthority.

AccessDecisionManager

The AccessDecisionManager is called by the AbstractSecurityInterceptor and is responsible for making final access control decisions.

The 3 functions included in the AccessDecisionManager are:

void decide(Authentication authentication,Object secureObject,Collection<ConfigAttribute> attrs)throwsAccessDeniedException;

boolean supports(ConfigAttribute attribute);

boolean supports(Class clazz);

The supports configAttribute is used during startup to determine the configuration being passed in will work properly with the AccessDecisionManager. 

The supports class determines whether the configured AccessDecisionManager will support the required secure object.

The decide method is used to determine authorization decisions. 

Hierarchical Roles

In most application it is common to have common roles assigned that distinguish control and access to the user, such as admin and users.  Admin having access to all areas of the application where users only have access to the most common areas.  There are various way one could implement roles assignment so to grant access.  For example, the role admin could be added to the role users so that admin had access to both admin and user access and then only grant authority to users amongst all objects or you could have admin, users assigned access to the objects needed full access to both roles. 

An example of a bean:

<beanid=”roleVoter”class=”org.springframework.security.access.vote.RoleHierarchyVoter”><constructor-argref=”roleHierarchy”/>
</bean>
<beanid=”roleHierarchy”class=”org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl”>
    <propertyname=”hierarchy”>
        <value> ROLE_ADMIN > ROLE_STAFF ROLE_STAFF > ROLE_USER ROLE_USER > ROLE_GUEST </value>
    </property>
</bean>

As you can see in the above example the ROLE_ADMIN has access to 4 roles where ROLE_USER only has 2.

Secure Object Implementations

AOP Alliance Security Interceptor

Method security in enforced using a MethodSecurityInterceptor, which secures MethodInvocations. Depending on the configuration approach, an interceptor may be specific to a single bean or shared between multiple beans.

Bean example:

<bean id=”bankManagerSecurity”
class=”org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor”>
<property name=”authenticationManager” ref=”authenticationManager”/>
<property name=”accessDecisionManager” ref=”accessDecisionManager”/>
<property name=”afterInvocationManager” ref=”afterInvocationManager”/>
<property name=”securityMetadataSource”>
<value>
com.mycompany.BankManager.delete*=ROLE_SUPERVISOR
com.mycompany.BankManager.getBalance=ROLE_TELLER,ROLE_SUPERVISOR
</value>
</property>
</bean>

Aspect J Security Interceptor

The AspectJ interceptor is named AspectJSecurityInterceptor. Unlike the AOP Alliance security interceptor, which relies on the Spring application context to weave in the security interceptor via proxying, the AspectJSecurityInterceptor is weaved in via the AspectJ compiler.

Bean Example:

<bean id=”bankManagerSecurity”
class=”org.springframework.security.access.intercept.aspectj.AspectJSecurityInterceptor”>
<property name=”authenticationManager” ref=”authenticationManager”/>
<property name=”accessDecisionManager” ref=”accessDecisionManager”/>
<property name=”afterInvocationManager” ref=”afterInvocationManager”/>
<property name=”securityMetadataSource”>
<value>
com.mycompany.BankManager.delete*=ROLE_SUPERVISOR
com.mycompany.BankManager.getBalance=ROLE_TELLER,ROLE_SUPERVISOR
</value>
</property>
</bean>       

Expression Based Access Control

Uses a Boolean based logic to allow complex conditions for access control. 

ExpressionDescription

hasRole([role])

Returns true if the current principal has the specified role. This is a synonym for hasAuthority([authority])

hasAnyRole([role1,role2])

Returns true if the current principal has any of the supplied roles (given as a comma-separated list of strings) This is a synonym for hasAnyAuthority([authority1,authority2])

hasAuthority([authority])

Returns true if the current principal has the specified authority. This is a synonym for hasRole([role])

hasAnyAuthority([authority1,authority2])

Returns true if the current principal has any of the supplied roles (given as a comma-separated list of strings) hasAnyRole([role1,role2])``hasAnyRole([role1,role2])

principal

Allows direct access to the principal object representing the current user

authentication

Allows direct access to the current Authentication object obtained from the SecurityContext

permitAll

Always evaluates to true

denyAll

Always evaluates to false

isAnonymous()

Returns true if the current principal is an anonymous user

isRememberMe()

Returns true if the current principal is a remember-me user

isAuthenticated()

Returns true if the user is not anonymous

isFullyAuthenticated()

Returns true if the user is not an anonymous or a remember-me user

hasPermission(Object target, Object permission)

Returns true if the user has access to the provided target for the given permission. For example, hasPermission(domainObject, 'read')

hasPermission(Object targetId, String targetType, Object permission)

Returns true if the user has access to the provided target for the given permission. For example, hasPermission(1, 'com.example.domain.Message', 'read')

An example based on role and ipaddress:

 

<http use-expressions=”true”>
<intercept-url pattern=”/admin*”
access=”hasRole(‘admin’) and hasIpAddress(‘192.168.1.0/24′)”/>

</http>

Method Security Expressions

There are four annotations which support expression attributes to allow pre and post-invocation authorization checks and also to support filtering of submitted collection arguments or return values. They are @PreAuthorize, @PreFilter, @PostAuthorize and @PostFilter.

@PreAuthorize(“hasRole(‘ROLE_USER’)”)
publicvoid create(Contact contact);

@PreFilter(“#c.name == authentication.name”)
publicvoid doSomething(@P(“c”)Contact contact);

@PostAuthorize(“hasRole(‘ROLE_USER’)”)

@PostFilter(“hasPermission(filterObject, ‘read’) or hasPermission(filterObject, ‘admin’)”)
publicList<Contact> getAll();

In conclusion, we reviewed a lot of topic areas covered in Spring Security.  We covered a vary of aspects of security such as securing access to various areas of the application and also threat based security.  Web applications have been focused on access based security and is almost always provided in enterprise applications.  From a threat point of view, we often don’t take as much time to worry about this side of the security concern and it will become in the near future a larger focus for applications, especially those out on the cloud or open to the internet.





Posted in Spring | Tagged , , , | Leave a comment

5 Must-Have Pages for a Business Web Site

Some information is expected to be present on a business web site. Visitors want to learn more about the company and also gain a level of confidence from the web site content. Most importantly, you want to encourage potential customers to take the next step and make contact. Along with the home page, the 5 pages listed below help provide visitors with more information and a degree of confidence.

  • About Us – This is often the 1st page visited after the home page. People want to know more about the company and its history. However, steer clear of adding too much text. Visitors eyes will glaze over and the important pieces if information will be lost among the “fluff.”
  • Contact Us – The goal of nearly every business web site owner is to convert a visitor to a customer. The first step is to have the visitor contact you. The contact page should show all forms of contact (address, phone, e-mail). Contact form should ask for minimal information so as not to scare away a potential customer. Only name and 1 contact method, usually an e-mail address, should be required.
  • Services/Products – What does your company do? What services and/or products do you offer? This is the place to convey the company’s value proposition and also give a bit of a sales pitch.
  • Testimonials – No advertising is more powerful than positive reviews from current and former clients/customers. This gives potential customers a feeling of security and trust.
  • Privacy Policy – To make a potential customer feel comfortable about making contact and providing contact information, however minimal, it is essential to have a privacy policy page explaining how gathered information is (not) used. This is absolutely essential on shopping web sites and will decrease the frequency of shopping cart abandonment. A link to the privacy policy should appear on every page, usually in the footer.





Posted in eBusiness | Tagged , , | Leave a comment

ASP.NET C# – Numeric TextBox control validation

There are times when you need to ensure numeric values are entered into a TextBox control.
This can be accomplished using a CompareValidator with the Operator attribute set to "DataTypeCheck" and Type attribute set to the numeric type (Double or Integer).

The sample below allows only double values in the TextBox control.
<asp:TextBox ID="Mileage" runat="server" Columns="8"></asp:TextBox>
...
<asp:CompareValidator ControlToValidate="Mileage" Operator="DataTypeCheck"
 ID="MileageValidator" runat="server" Type="Double"
 Display="Dynamic" ErrorMessage="Please enter a valid mileage amount.">
</asp:CompareValidator>





Posted in Web Development | Tagged , , | Leave a comment