Web Applications

03
Jan

Why DOCTYPE is so important

Posted by eugene as Web Applications

Almost all is done correctly but your website doesn’t look ghe way you want or doesn’t work as you expectd in the last browser versions.

You’ve written correct and standard XHTML code and standard CSS. You’ve used standard specification for work with DOM (Document Object Model) in order to manage the dynamic elements on the page. And hence, in browsers which seem to be made with compliance of exactly these standards, your website doesn’t work. Most likely, the error is hidden the incorrect DOCTYPE heading.

This little article will tell you about the DOCTYPE headings which work and also will explain the practic and theoretic meaning of this, seems to be abstract from reality tag.

What is DOCTYPE?

According to the HTML and XHTML documentation the DOCTYPE tag (which means “document type declaration”) tells validator which version exactly (X)HTML you use on your website. This tag must be located in the first line of each page. The DOCTYPE tag is the key component of web-pages which pretends for the corresponding standards.

As it’s been said in the previous articles (and also in other articles on other websites). the DOCTYPE tag is also important for correct displaying and work of the page in browsers relating to the standards (Mozilla, IES/Mac, and IE6/Win).

The full URL is specified in the attributes of the DOCTYPE tag which tells browsers that the page should be shown with compliance of the definite standard and subtype of this standard.

If you will use the incomplete DOCTYPE tag, its old type or fully forget about it, the browser will go into the “puzzle” mode and it get on the assumptions that you wrote the page code with errors and voluntarily departed from the standards as in the end of the 90th wrote.

In this mode brower will try to recollect your page by the rules of the revert compatibility and will display CSS, for example, so as Internet Explorer 4 would have shown it, and DOM will work so as it would have worked exactly on this browser (IE switches into its old DOM, Mozilla and Netscape 6 switch into something God knows what).

It is clear that freaks are not desirable for you. But that is what you get if you use incomplete or incorrect DOCTYPE tag. This article will help you to rectify this error.

(Attention: the Opera browser doesn’t work by these rules; it always tries to display the page so as it would correspond to the standards. Fame to Opera! From another side, Opera does not fully support the W3C DOM standard but the work on it is already going on.)

Where to download the correct DOCTYPE?

As the DOCTYPE tags are extremely important for working of Web by standards as the W3C consortium is the leading organization which creates standards for Web, it might be necessary to anticipate that the W3C website will represent the list of all versions of the DOCTYPE tag and it seems you can easily find this information on the W3C webiste and simply in some definite chapter. But it is not so, at least at the moment of writing this article.

W3.org is not a website with articles as A List Apart, WebReference or Webmonkey. It is not created in order tp help web-designers, developers and website authors =, and it doesn’t participate in distributing the newest information and usefull advices. This is not its task.

Sometimes W3C publishes a series of courses and tutorials though most web-applications don’t know about it. And when I say about engineers, I don’t mean simple specialists in the area of web-development, such specialists as you and I. I mean engineers in comparison with which we look full idiots.

I can spend all day searching for the correct DOCTYPE tag (for example, the mentioned in any Recommendation or Work project), sooner it won’t work on your website.

Over the whole W3X website DOCTYPE tags are spread where URL is absent in the attributes, and DOCTYPE tags containing the relative URL in the attributes connected with the documents located on the same W3C website. If you take this tag from the W3C website, move it onto your website and insert into your pages, the relative URL will point out on the non-existing documents on your website, hence your hard work and browser efforts will be lost needlessly.

For example, on many websites you can see the following version of the DOCTYPE tag which has been moved from website w3.org without any changes:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">

Pay attention that the DOCTYPE version contains full URL in the end. And as the tag points on the correct document location placed on the W3C website. As the core document is located on the W3C website and not on yours this URL is needless for the browser.

Correct versions of the DOCTYPE tag

HTML 4.01 Strict standard, Transitional, Frameset

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">

XHTML 1.0 Strict, Transitional, Frameset

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">

XHTML 1.1 DTD standard

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

What is next?

How can you contribute into the distribution of standards in Web? At first, put into your favourites this page (or simply save it on your PC) and also check if your web-editor inerts the DOCTYPE tag into your web-pages and if so – whether it uses the correct tag version?

Most developers simply copied incomplete versions of the DOCTYPE tag from W3C into their programs. And as the result you rely on on a program that inserts the wrong version of the tag, the browser runs into the “mysterious” mode, and you’re fighting unsuccessfully over the mystery about why your page is not working as it should.

It is also worth to write those guys what develop your favourite web-editor and show them how the correct DOCTYPE tag looks like, and after that politely ask them to make changes into the new version of the program. (In some cases you can even put changes into the program by yourself.

In the nearest future

We have every reason to hope that W3C will soon put a complete, accurate and convenient list of all the versions of the DOCTYPE tag on its website, and also it will publish other useful information. And it will be easy to find this information. Of course, this articly is highly contributed by Karl Dabost – conformance manager of W3C’s Quality Assurance team.

The Web Standards project will sonn be remade (very soon) and you can also find this information on it.

But as new and more new websites are created and released every day, this information is already necessary now, so here it is – use it.

Good luck!

24
Dec

Authorization on the website via API of social networks with integration into Spring Security

Posted by eugene as Spring Framework, Web Applications

I’ve decided to implement authorization (registration) on the prepared website and to identify users with the help of the social network developer instrument (Social Networks REST API) – tge subject is not far innovative, widely used and very easy to use. I won’t list all the benefits and convenience of using such functionality on their websites, but I want to admit that I am very happy not to remember passwords for each website (even I have a couple of standard used), not to engage in long and boring registration with sending mails and acknowledgements, and do not deal with captchas again and so on.

The API data functionality is rather primitive, simple technology and implementation is quite similar and simple. But when you familiarize with the technology, it is not only enough to have API documentation and social networking examples. In addition, as described in the topic, the used language is Java which automatically reduces the amount of useful information. And there’s no too much information in RU net either. You can follow the path of the least resistance and use the third-party RESTful products, but a) it doesn’t give full understanding of the process, and b) reduces the switching properties of the desired process; c) the third-party product research often can be more difficult that the development of its implementation. While ease of use of such third-party product can facilitate the development at times. However I’ve put the emphasis on making the most control over all processes in this review even at the expense of universality (we “fasten” specific functionality to the particular site, and only a few make the versatile product “for all life occasions” out of it). In addition, I am interested not only how to implement the authentication of users, but also to invent it into the project security system which is provided by the Spring Security 3 framework.

The used set of platforms and tools is: Spring Core 3.1, Spring MVC 3.1, Spring Security 3.1, Hibernate 4.1. The implementation project is foreig, therefore a set of introduced social networks is standard “for them” – Facebook, Twitter, Google+, Linkedin.

I want to admit that a ready “out of the box” project is available in the Spring package – Spring Social (for now is release 1.0.2) which is currently encapsulated in a wonderful Spring-framework product. Surely it would have been a professional solution but our task is to control everything and make the process as transparent for understanding as possible. And it’s not so good with Social itself.

1. Model.

I’ve chosen a little risky and controversial way, combining the user and POJO, and UserDetails, and Entity in the object. In terms of the programming approach this is wrong but: a) it’s very convenient; and b) saves the creation of severeal layers which saves us to make separate POJO+Entity, separately UserDetails and separately DTO which actually duplicates the content.

The proposed scheme of model construction looks like the following:

Model

I’ve identified two layers (AuthUser and DataUser) in order not to interfere with authorization logic with the business logic of the project: both the visitor and the manager and whoever else – will be authenticated the same but will have their own set of properties. For example, in my project there’re Jobseekers and Employers, the same way get to the website but they have completely different structure of the model.

As for the separation of structure within the layers, this is obvious – a set of the received fields from Facebook, Twitter and so on, and especially during the standard authorization, is so different that to create the entire terribly stretched structure for everything is just silly and in terms of building a database – redundant. As per scalability, when adding a new service provider the work with such a structure would be extremely uncomfortable.

Below are the listings of some objects, and also the used enum classes.

AuthUser.java:

@ Entity
    @ Table(name = "auth_user")
    @ Inheritance(strategy = InheritanceType.JOINED)
    public class AuthUser implements Serializable, UserDetails {
        @ Id
        @ Column(name = "id")
        @ GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;
 
        @ Column(name = "identification_name", length = 64, nullable = false)
        private String identificationName;
 
        @ Enumerated(EnumType.STRING)
        @ Column(name = "type", nullable = false)
        private AuthorityType type;
 
        @ Column(name = "binary_authorities", nullable = false)
        private Long binaryAuthorities;
 
        @ Column(name = "enabled", nullable = false, columnDefinition = "tinyint")
        private Boolean enabled;
 
        @ Transient
        private Set<Authority> authorities;
 
        @ OneToOne(fetch = FetchType.LAZY, orphanRemoval = true)
        @ Cascade({CascadeType.ALL})
        @ JoinColumn(name="user_id")
        private User user;
 
        @ Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            authorities = EnumSet.noneOf(Authority.class);
            for (Authority authority : Authority.values())
            		if ((binaryAuthorities & (1 << authority.ordinal())) != 0)
                    authorities.add(authority);
            return authorities;
        }
        public void setAuthority(Set<Authority> authorities) {
            binaryAuthorities = 0L;
            for (Authority authority : authorities)
                binaryAuthorities |= 1 << authority.ordinal();
        }
        @ Override
        public String getPassword() {
            return type.name();
        }
        @ Override
        public String getUsername() {
            return identificationName;
        }
        @ Override
        public boolean isAccountNonExpired() {
            return true;
        }
        @ Override
        public boolean isAccountNonLocked() {
            return true;
        }
        @ Override
        public boolean isCredentialsNonExpired() {
            return true;
        }
 
        //getters/setters
    }

AuthorityType.java:

public enum AuthorityType implements Serializable {
        SIMPLE, FACEBOOK, TWITTER, GOOGLE, LINKEDIN;
    }

Authority.java:

public enum Authority implements GrantedAuthority {
        NEW_CUSTOMER, CUSTOMER, ADMINISTRATOR;
 
        @ Override
        public String getAuthority() {
            return toString();
        }
    }

FacebookAuthUser.java:

@ Entity
    @ Table(name = "facebook_auth_user")
    public class FacebookAuthUser extends AuthUser {
        @ Column(name = "first_name", length = 32)
        private String firstName;
 
        @ Column(name = "last_name", length = 32)
        private String lastName;
 
        @ Column(name = "email", length = 64)
        private String email;
 
        @ Column(name = "token", length = 128)
        private String token;
 
        //any number of available properties
        //getters/setters
    }

TwitterAuthUser.java:

@ Entity
    @ Table(name = "twitter_auth_user")
    public class TwitterAuthUser extends AuthUser {
        @ Column(name = "screen_name", length = 64)
        private String screenName;
 
        @ Column(name = "oauth_token", length = 80)
        private String oauthToken;
 
        @ Column(name = "oauth_token_secret", length = 80)
        private String oauthTokenSecret;
 
        //any number of available properties
        //getters/setters
    }

SimpleAuthUser.java:

@ Entity
    @ Table(name = "simple_auth_user")
    public class SimpleAuthUser extends AuthUser {
        @ Column(name = "password", length = 40, nullable = false)
        private String password;
 
        @ Column(name = "uuid", length = 36, nullable = false)
        private String uuid;
 
        @ Override
        public String getPassword() {
            return password;
        }
 
        //getters/setters
    }

As you can see, it’s not all enough without the slightest “magics”:

  • I don’t want to do one more structure (table) for storing user roles and to miss the opportunity to assign a user multiple roles changing a set of roles for another one is weird. Therefore I store a binary representation of the set of roles in the database, and I feed the set to Spring Security. The main thing is to remember to make a transformation while reading from the database. Ideologically it’s not correct to hold the transformation mechanism in POJO, it is necessary to leave it in the controller or DAO, but let’s assume it costs of publication.
  • The type field (AuthorityType enum) – it doesn’t carry the special need rather to visualize data in the database, plus it’s easier to use user.getType() in the representation rather than investigate the belonging to one of the classes – user insteadof TwitterAuthUser, even though it’s not important.
  • The UserDetails interface requires to implement a number of methods. In particular, identificationName (and getUsername()) is the field that stores the identifiers: FacebookID for Facebook, TwitterID for Twitter, nickname or email for the standard authorization. The getPassword() method in my case returns that same type, further it will be used by Spring Security in order to form hash cookies in the RememberMe mechanism. In order to improve the project security in every class you can redefine this method by assigning the secure data to it, as I’ve done this in the SimpleAuthUser class. For others it can be tokens or secret tokens. What to do next with the methods and potentially corresponding to them isAccountNonExpired, isAccountNonLocked, isCredentialsNonExpired properties – to decide as appropriate of using such data, in this review I don’t use them drowning return true.

As you can see in the scheme and code, I’ve decided to use the lazy dependency between the objects of different layers, even though they are interrelated as “one-to-one”. There’re two objectives: 1) AuthUser often twitches by framework in the controller and view, and there’s no great desire to pull the dependent structure all over itself, moreover it can be quite extended and massive (I have almost 5-6 EAGER dependencies in the Jobseeker tables of the project, not counting LAZY – these are both phone numbers, and address, and proffessions and so on), that’s why in my opinion the safe side will not prevent. 2) you shouldn’t forget that these layers are related to different logics layers: AuthUser is twitching by the Spring Security framework, and in parallel the changes can occur in DataUser, and there’s no much desire to engage in constant tracking and updating. I agree that the decision is dispute and it does not claim to be definitive. Perhaps it is necessary to link the contrary, thus the listed problems will be gone, but the business logic, you can always pull the authorization bean. It’s left up to the developers.

What’s related to the DataUser class and the dependent these are the simple POJO classes, directly DataUser contains common for all properties (e.g. id, firstName, lastName, email, location) and the rest expand it by adding the specific for them properties (it’s impractical to show the listings).

2. Controller.

Basically in terms of authentication and authorization there’s no much difference, and verious network providers predispose these terms in their own way. However, I clearly distinguish two concepts in this report – registration and the authorization itself or input (both are based on the authorization in the social network provider). For example, when participating on forum or submitting comments you simply should log in – whether it is the first entry or the hundredth. In my division for registration and basic authorization I am chasing the need to create a user model in the application for registartion. And while it might be easier to implement – at the entrance check – whether such person exists or not – and create the user structure in case of the first entry. But a) there exists a standard registration and it’s logical to make visual division “here is one thing and there another one” (notorious usability); b) how it’s not disappointing but API of the social networks are not agreed to provide information about their clients – for example, Facbook API provides email, name, gender, location; Twitter API provides screen_name, which may not necessarily be “a name or surname”, doesn’t provide email (they have a position to clearly distinguish reality and virtuality); Google+ API provides name, last name, email but nothing about location; LinkedIn API – name, last name, gender, location but doesn’t provide email. Since my project is very closely tied to the personal visitor data (project for the recruiting company), together with the registration I point to the need to fill in some fields (initially except the Facebook users all had to specify something, now is simplified and such need exists only for Twitter users, though I do not exclude a complete failure and the filling of fields will be simply just needed, for example when trying to get into the “zone”). Therefore my implementation is a bit overblown, though it only helps to understand better the mechanism of authentication.

I want to recall that it’s necessary to create your own application in every social network and to use its settings for work (or testing). This is developers.facebook.com/apps for Facebook, dev.twitter.com/apps for Twitter, code.google.com/apis/console for Google+, www.linkedin.com/secure/developer for LinkedIn. When creating an application there exist three important parameters which are available in every provider – key (API key, Consumer key, Client ID), secret key (App Secret, Consumer Secret, Client Secret, Secret key) and the redirect address (say, until recent time some providers’ localhost redirect didn’t work properly, but for now all is tested – all work with the address type of http://localhost:8080/myproject). There you can configure other settings, including the logo of the application, however, Linkedin requires the SSL link to the image (strange wish).

Facebook and Google+ have been using new OAuth 2 protocol, Twitter and LinkedIn are still on the older OAuth protocol (Google+ also supported the first OAuth version till the 20th of April, 2012). Due to my descretion (although I can’t imagine that there could be another opinion) it’s immeasurably easier and more convenient to work with OAuth 2, however, despite the fact that it’s quite popular, it still hasn’t been approved as standard. The concept of its work is rather primitive (the most popular scheme).

pic2

Thus, a user clicks one of the registration buttons on the web page:

capt

(and I don’t leave any “extra” functionality on the page, just a button with the address like www.myproject.com/registration/facebook and so on), the request will get into the controller (for Facebook).

@ RequestMapping(value = "/registrate/facebook", method = RequestMethod.POST)
    public ModelAndView facebookRegistration() throws Exception {
        return new ModelAndView(new RedirectView(FACEBOOK_URL + "?client_id=" + FACEBOOK_API_KEY +
            + "&redirect_uri=" + FACEBOOK_URL_CALLBACK_REGISTRATION +
            + "&scope=email,user_location&state=registration", true, true, true));
    }

The scope parameters can be found at developers.facebook.com/docs/authentication/permissions (for Twitter – dev.twitter.com/docs/platform-objects/users, Google+ – developers.google.com/accounts/docs/OAuth2Login#userinfocall, LinkedIn – developer.linkedin.com/documents/profile-fields), I’ve put only the couple of examples. The redirect_uri domain must match the registered address of the date application. state is the “free” parameter which I use as the semaphor for the further actions – registration, signin, autosignin.

Then the user is being redirected to the root Facebook authorization page where it will allow the application to use its data, and if the resolution are going out of the basic scopes, they will be listed in the authentication window.

After authorization our controller with the FACEBOOK_IRL_CALLBACK_REGISTRATION mapping gets a call (in any client’s decision – authenticate, cancel, return). Spring MVC allows us to filter the requests by mapping at once (in this case here is the mapping of my project):

@ RequestMapping(value = "/callback/facebook", method = RequestMethod.GET)
    public class FacebookController extends ExternalController implements Constants {
        @ RequestMapping(value = "/registration", params = "code")
        public ModelAndView registrationAccessCode(@ RequestParam("code") String code, HttpServletRequest request) throws Exception {
            String authRequest = Utils.sendHttpRequest("GET", FACEBOOK_URL_ACCESS_TOKEN, new String[]{"client_id", "redirect_uri", "client_secret", "code"}, new String[]{FACEBOOK_API_KEY, FACEBOOK_URL_CALLBACK_REGISTRATION, FACEBOOK_API_SECRET, code});
            String token = Utils.parseURLQuery(authRequest).get("access_token");
    String tokenRequest = Utils.sendHttpRequest("GET", FACEBOOK_URL_ME, new String[]{"access_token"}, new String[]{token})
            Map<String, Json> userInfoResponse = Json.read(tokenRequest).asJsonMap();
            String email = userInfoResponse.get("email").asString().toLowerCase();
            String id = userInfoResponse.get("id").asString();
            //verifying ... is new? is email in DB?
            //creating objects
            Customer customer = new Customer();
            customer.setEmail(email);
            //...
            customerer = (Customerer) userDAO.put(customer);
            FacebookAuthUser user = new FacebookAuthUser();
            user.setFirstName(firstName);
            //...
            user.setIdentificationName(id);
            user.setToken(token);
            user.setType(AuthenticationType.FACEBOOK);
            user.setEnabled(true);
            user.setAuthority(EnumSet.of(Authority.CUSTOMER));
            user.setUser(customer);
            authenticationDAO.put(user);
            return new ModelAndView(new RedirectView("/registrate.complete", true, true, false));
        }
 
        @ RequestMapping(value = "/registration", params = "error_reason")
        public ModelAndView registrationError(@ RequestParam("error_description") String errorDescription, HttpServletRequest request, HttpServletResponse response) {
            //return client to registration page with errorDescription
            return new ModelAndView(new RedirectView("/registrate", true, true, false));
        }
        //will signin and signinError
    }

For convenience and the unitary using, here is a couple of static methods of the Utils class used in this listing:

public static String sendHttpRequest(String methodName, String url, String[] names, String[] values) throws HttpException, IOException {
        if (names.length != values.length) return null;
        if (!methodName.equalsIgnoreCase("GET") && !methodName.equalsIgnoreCase("POST")) return null;
        HttpMethod method;
        if (methodName.equalsIgnoreCase("GET")) {
            String[] parameters = new String[names.length];
            for (int i = 0; i < names.length; i++)
                parameters[i] = names[i] + "=" + values[i];
            method = new GetMethod(url + "?" + StringUtils.join(parameters, "&"));
        } else {
            method = new PostMethod(url);
            for (int i = 0; i < names.length; i++)
                ((PostMethod) method).addParameter(names[i], values[i]);
            method.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        }
        new HttpClient().executeMethod(method);
        return getStringFromStream(method.getResponseBodyAsStream());
    }
    public static Map<String, String> parseURLQuery(String query) {
        Map<String, String> result = new HashMap<String,String>();
        String params[] = query.split("&");
        for (String param : params) {
            String temp[] = param.split("=");
            try {
                result.put(temp[0], URLDecoder.decode(temp[1], "UTF-8"));
            } catch (UnsupportedEncodingException exception) {
                exception.printStackTrace();
            }
        }
        return result;
    }

Constants:

final public static String FACEBOOK_API_KEY = "XXXXXXXXXXXXXXXX";
    final public static String FACEBOOK_API_SECRET = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    final public static String FACEBOOK_URL = "https://www.facebook.com/dialog/oauth";
    final public static String FACEBOOK_URL_ACCESS_TOKEN = "https://graph.facebook.com/oauth/access_token";
    final public static String FACEBOOK_URL_ME = "https://graph.facebook.com/me";
    final public static String FACEBOOK_URL_CALLBACK_REGISTRATION = SITE_ADDRESS + "/callback/facebook/registration";
    final public static String FACEBOOK_URL_CALLBACK_SIGNIN = SITE_ADDRESS + "/callback/facebook/signin";

Everyone can use JSON libraries up to its own discretion, I used the mjson library (http://sharegov.blogspot.com/2011/06/json-library.html) – small, convenient and without serialization.

As you can see, the process is simple and should not cause any special problems. I’d like to note that Facebook provides the location parameter and its value can be “pulled” to Google Maps API (by following http://maps.googleapis.com/maps/api/geocode/json) and to get geolocation in the convenient form (due to the standards of Google Maps). It’s clear it can be only in case the customer specified not only the location country in his account in Facebook.

The registration in Google+ is performed the same way, with the only difference that the callback URL in their system should be fully identical to that specified in the application settings. Thus, all the redirects will get only only to one mapping. It’s convenient to use the returned state parameter for the separation of processes.

@ RequestMapping(value = "/callback/google", method = RequestMethod.GET)
    public class GoogleController extends ExternalController implements Constants {
        @ RequestMapping(value = {"/", ""}, params = "code")
        public ModelAndView googleProxy(@ RequestParam("code") String code, @ RequestParam("state") String state, HttpServletRequest request, HttpServletResponse response) throws Exception { ... }
 
        @ RequestMapping(value = {"/", ""}, params = "error")
        public ModelAndView googleErrorProxy(<hh user=RequestParam>("error") String error, <hh user=RequestParam>("state") String state, HttpServletRequest request) throws Exception { ... }
    }

The other actions, except of the addresses and the returned parameters are identical.

Otherwise the thing is going with the authorization over the OAuth protocol (Twitter and LinkedIn). I’ve gone through the whole chain of authentication but it’s very uncomfortable because of the forming of request with tokens – they should be “glued” packed by base64 in a special way, to add the timing parameters and to make other manipulations. And what’s the most surprising – the sections for social network developers do not reflect these processes. Though this is a standard, so the count is performed due to the standard approach. In any case authorization in this way is implemented “manually” and it is not of the interest for the development of your own application. I suggest to use other free libraries that facilitate this task. For example, there exists a library specifically for Twitter – twitter4j.jar. I used the scribe-java library (http://github.com/fernandezpablo85/scribe-java) which is distributed on the terms of MIT license. The package contains work with Digg API, Facebook API, Flickr API, Freelancer API, Google API, LinkedIn API, Skyrock API, Tumblr API, Twitter API, Vkontakte API, Yahoo API and two dozens of some others.

The registration process for Twitter with the usage of the scribe library will look in the following way. The client request controller for authorization from the registration page:

@ RequestMapping(value = "/registrate/twitter", params = "action", method = RequestMethod.POST)
    public ModelAndView twitterRegistrationJobseeker(HttpServletRequest request) throws Exception {
        OAuthService service = new ServiceBuilder().provider(TwitterApi.class)
            .apiKey(TWITTER_CONSUMER_KEY).apiSecret(TWITTER_CONSUMER_SECRET)
            .callback(TWITTER_URL_CALLBACK_REGISTRATION).build();
        Token requestToken = service.getRequestToken();
        request.getSession().setAttribute("twitter", service);
        request.getSession().setAttribute("request_token", requestToken);
        return new ModelAndView(new RedirectView(service.getAuthorizationUrl(requestToken), true, true, true));
    }

Twitter callback controller:

@ RequestMapping(value = "/callback/twitter", method = RequestMethod.GET)
    public class TwitterController extends ExternalController implements Constants {
        @ RequestMapping(value = "/registration", params = "oauth_verifier")
        public ModelAndView registrationAccessCode(@ RequestParam("oauth_verifier") String verifier, HttpServletRequest request, HttpServletResponse response) throws Exception {
            OAuthService service = (OAuthService) request.getSession().getAttribute("twitter");
            Token accessToken = service.getAccessToken((Token) request.getSession().getAttribute("request_token"), new Verifier(verifier));
            OAuthRequest oauthRequest = new OAuthRequest(Verb.GET, TWITTER_URL_CREDENTIALS);
            service.signRequest(accessToken, oauthRequest);
            Map<String, Json> userInfoResponse = Json.read(oauthRequest.send().getBody()).asJsonMap();
            String twitterId = userInfoResponse.get("id").asString();
            //verifying ...
            Customer customer = new Customer();
            customer.setFirstName((String) request.getSession().getAttribute("pageValueFirstName"));
            //...
            customer = (Customer) userDAO.put(customer);
            TwitterAuthUser user = new TwitterAuthUser();
            user.setAuthority(EnumSet.of(Authority.CUSTOMER));
            user.setIdentificationName(twitterId);
            //...
            user.setOauthToken(accessToken.getToken());
            user.setOauthTokenSecret(accessToken.getSecret());
            user.setType(AuthenticationType.TWITTER);
            user.setUser(customer);
            authenticationDAO.put(user);
            return new ModelAndView(new RedirectView("/registrate.complete", true, true, false));
        }
 
        @ RequestMapping(value = "/registration", params = "denied")
        public ModelAndView registrationError(HttpServletRequest request) {
            //response does not contain the error text
            return new ModelAndView(new RedirectView("/registrate", true, true, false));
        }
        //will signin and signinError
    }

Once again, all is easy and affordable. Registration via LinkedinAPI is performed in a quite the same way.

And the last – registration in a standard way. Standard – hence it’s standard, I won’t show the source code, will only note that we create an object of the SimpleAuthUser type inherited from AuthUser:

    SimpleAuthUser user = new SimpleAuthUser();
        user.setAuthority(EnumSet.of(Authority.NEW_CUSTOMER));
        user.setEnabled(false);
        user.setIdentificationName(email);
        user.setPassword(passwordEncoder.encodePassword(password, email));
        user.setType(AuthenticationType.SIMPLE);
        user.setUser(customer);
        user.setUuid(uuid);
        authenticationDAO.put(user);

For this case the NEW_CUSTOMER authority needed – registered user needs confirmation of registration (standard practice), and that’s why a) it has a different role; b) it’s not allowed for authorization in Spring Security (enabled = false).

Authorization on the website

A simple spring application-context-security.xml:

<security:global-method-security secured-annotations="enabled" jsr250-annotations="enabled" pre-post-annotations="enabled" proxy-target-class="true"/>
 
    <security:http auto-config="true" use-expressions="true">
        <security:intercept-url pattern="/**" access="permitAll"/>
        <security:form-login login-page="/signin"/>
        <security:logout invalidate-session="true" logout-success-url="/" logout-url="/signout"/>
        <security:remember-me services-ref="rememberMeService" key="someRememberMeKey"/>
    </security:http>
 
    <security:authentication-manager alias="authenticationManager">
        <security:authentication-provider ref="authenticationProvider"/>
    </security:authentication-manager>
 
    <bean id="authenticationProvider" class="myproject.security.CustomAuthenticationProvider"/>
 
    <bean id="rememberMeService" class="myproject.security.RememberMeService">
<property name="key" value="someRememberMeKey"/>
<property name="userDetailsService" ref="userDetailsService"/>
    </bean>
 
    <bean id="userDetailsService" class="myproject.security.CustomUserDetailsManager"/>
    <bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder"/>

CustomUserDetailsManager.java:

public class CustomUserDetailsManager implements UserDetailsService {
        @ Resource private AuthenticationDAO authenticationDAO;
 
        @ Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            return authenticationDAO.findAuthUser(username);
        }
    }

CustomUserAuthentication.java:

public class CustomUserAuthentication implements Authentication {
        private String name;
        private Object details;
        private UserDetails user;
        private boolean authenticated;
        private Collection<? extends GrantedAuthority> authorities;
 
        public CustomUserAuthentication(UserDetails user, Object details) {
            this.name = user.getUsername();
            this.details = details;
            this.user = user;
            this.authorities = user.getAuthorities();
            authenticated = true;
        }
 
        @ Override
        public String getName() {
            return name;
        }
        @ Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            return authorities;
        }
        @ Override
        public Object getCredentials() {
            return user.getPassword();
        }
        @ Override
        public Object getDetails() {
            return details;
        }
        @ Override
        public Object getPrincipal() {
            return user;
        }
        @ Override
        public boolean isAuthenticated() {
            return authenticated;
        }
        @ Override
        public void setAuthenticated(boolean authenticated) throws IllegalArgumentException {
            this.authenticated = authenticated;
        }
    }

CustomAuthenticationProvider.java

(the class is completely clueless, but the interface inheritant AuthenticationProvider should be fed to Spring Security, but the nearest PreAuthenticatedAuthenticationProvider doesn’t fit in meanning):

public class CustomAuthenticationProvider implements AuthenticationProvider {
        @ Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            //тут могут быть доп. проверки
            return authentication;
        }
 
        @ Override
        public boolean supports(Class<?> authentication) {
            return PreAuthenticatedAuthenticationToken.class.isAssignableFrom(authentication);
        }
 
        public Authentication trust(UserDetails user) {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            Authentication trustedAuthentication = new CustomUserAuthentication(user, authentication.getDetails());
            authentication = authenticate(trustedAuthentication);
            SecurityContextHolder.getContext().setAuthentication(authentication);
            return authentication;
        }
    }

And perhaps the most “narrow” place of security organization is the implementation of the RememberMe mechanism. Basically, everything is already organized so that the work of the RememberMe service fully corresponds to the TokenBasedRememberMeServices implementation, with the only clarification: all the data for automatic client authentication are located in our database, however there can be a situation when the user has already registered on the website and then removed his account on the used social network. And the result is conflict – we authorize the user but in fact he doesn’t exist, i.e. the basic authentication principles by using the third-party services are disrupted. Hence, when the RememberMe mechanism works out we should check the automatically logging client. Such mechanisms are present in every API network provider but we should “intrude” in the work of Spring RememberMe in order to perform the test at the right stage. Unfortunately, it’s not possible to expand some class (the required method is set as final in AbstractRememberMeServices), that’s why you need to completely redefine the class. My way is more cumbersome, I went from the end, abd the trivial human laziness doesn’t permit us to remodel it into the simplier version. I completely redefined the AbstractRememberMeServices class including the TokenBasedRememberMeServices class code, and by adding a couple of strings into the public Authentication autoLogin(HttpServletRequest request, HttpServletResponse response) method – after checking the values in the method but before the actual authentication I’ve put a check method call of the client “reality existance”.

Class<? extends ExternalController> controller = externalControllers.get(user.getPassword()); 
    if (controller != null && !controller.newInstance().checkAccount(user)) return null;

And before, I define the static list in the constructor:

private Map<String, Class<? extends ExternalController>> externalControllers;
 
    public CustomRememberMeService() {
        externalControllers = new HashMap<String, Class<? extends ExternalController>>(){{
            put(AuthenticationType.FACEBOOK.name(), FacebookController.class);
            put(AuthenticationType.TWITTER.name(), TwitterController.class);
            put(AuthenticationType.GOOGLE.name(), GoogleController.class);
            put(AuthenticationType.LINKEDIN.name(), LinkedinController.class);
        }};
    }

(this code implementation won’t affect the operation of RememberMe for standard authentication).

And a little easier method implies the replacement of the REMEMBER_ME_FILTER filter to its own where you should put the same code after the mentioned above autoLogin method call, but before the direct authentication. It is less expensive and to code and more logical to understand, however, it requires the intervention of the configuration file. Which way to go – everyone will decide himself, but the second one, in my opinion, is more ideologically “clear”.

Also you should clarify about ExternalController and checkAccount(user) call. All my callback-controllers extend the ExternalController class:

And each controller redefines this only method. For example, in regards to Facebook it’s:

public boolean ?heckAccount(UserDetails user) throws Exception {
        FacebookAuthUser facebookUser = (FacebookAuthUser) user;
        String authRequest = Utils.sendHttpRequest("GET", FACEBOOK_URL_ME, new String[]{"access_token"}, new String[]{facebookUser.getToken()});
        Map<String, Json> tokenInfoResponse = Json.read(authRequest).asJsonMap();
        return tokenInfoResponse.get("error") == null && tokenInfoResponse.get("id").asString().equalsIgnoreCase(facebookUser.getIdentificationName());
    }

and for Twitter:

public boolean checkAccount(UserDetails user) throws Exception {
        TwitterAuthUser twitterUser = (TwitterAuthUser) user;
        OAuthService service = new ServiceBuilder().provider(TwitterApi.class).apiKey(TWITTER_CONSUMER_KEY).apiSecret(TWITTER_CONSUMER_SECRET).build();
        OAuthRequest oauthRequest = new OAuthRequest(Verb.GET, TWITTER_URL_CREDENTIALS);
        service.signRequest(new Token(twitterUser.getOauthToken(), twitterUser.getOauthTokenSecret()), oauthRequest);
        String response = oauthRequest.send().getBody();
        Map<String, Json> info = Json.read(request).asJsonMap();
        return info.get("id").asString().equalsIgnoreCase(twitterUser.getIdentificationName());
    }

and so on.

And the authentication itself (login, sign in) is very similar to the registration. The user visits the page, clicks “Login” and he is being redirected to authentication:

The only thing is that I transfer the “signin” or “autosignin” parameter to the server, depending on the case if the “enter automatically” option is checked. Then all is happenning in a similar scenario with the registration, only the parameter and callback URL are changing and I put away all scope and permission – we need to get only the client ID and hist tokens. After the appropriate checks in the controller methods I suggest you to overwrite tokens into the database. And though, for example, Facebook didn’t change the client token during my tests, and Google+ does this every time. I don’t know how often the “change” happens, that’s why the overwrite is performed after eacb access_token receiving (in fact while each non-automatic authentication of the provider).

And the most important thing – the direct user authentication in Spring Security (definitely after all the checks for the correspondance and verification of rights from API provider), on the example of the Facebook controller:

@ RequestMapping(value = "/signin", params = "code")
    public ModelAndView signInAccessCode(@ RequestParam("code") String code, @ RequestParam("state") String state, HttpServletRequest request, HttpServletResponse response) throws Exception {
        String accessRequest = Utils.sendHttpRequest("GET", FACEBOOK_URL_ACCESS_TOKEN, new String[]{"client_id", "redirect_uri", "client_secret", "code"}, new String[]{FACEBOOK_API_KEY, FACEBOOK_URL_CALLBACK_SIGNIN, FACEBOOK_API_SECRET, code});
        String token = Utils.parseURLQuery(accessRequest).get("access_token");
        Map<String, Json> userInfoResponse = Json.read(Utils.sendHttpRequest("GET", FACEBOOK_URL_ME, new String[]{"access_token"}, new String[]{token})).asJsonMap();
        FacebookAuthUser user = (FacebookAuthUser) authenticationDAO.findAuthUser(userInfoResponse.get("id").asString(), AuthenticationType.FACEBOOK);
        if (user == null) {
            //something went wrong ...
            return new ModelAndView(new RedirectView("/signin", true, true, false));
        } else {
            if (!token.equals(user.getToken())) {
                user.setToken(token);
                user = (FacebookAuthUser) authenticationDAO.put(user);
            }
            Authentication authentication = customAuthenticationProvider.trust(user);
            if (state.equalsIgnoreCase("autosignin")) customRememberMeService.onLoginSuccess(request, response, authentication);
            else customRememberMeService.logout(request, response, authentication); //???????? ???? RememberMe
            return new ModelAndView(new RedirectView("/signin.complete", true, true, false));
        }
    }

Now the client will be automatically logged in when the flag is checked for auto logging in. Hence, if there’s no flag, the logout method call will erase cookies in the RememberMe service (it doesn’t do anything else). By the way, going over the “/logout” link takes the authentication off and cleans cookies automatically. This is overseen by the corresponding line in the Spring Security config above.

Using of the given method can be “atthached” for the standard authentication as well: after going through the checks (finding user in the table, matching password hash and so on) we manually authenticate him:

Authentication authentication = customAuthenticationProvider.trust(user);
    if (autosignin) customRememberMeService.onLoginSuccess(request, response, authentication);
    else customRememberMeService.logout(request, response, authentication);

There’s no difference in usage. The only thing is that while the RememberMe mechanism works out, there’ll be no external checks, in fact, it fully coincides with the work of the TokenBasedRememberMeServices service.

Then using of authentication is similar to using of general roles in Spring Security, with the only difference that you cannot use the @Secured(«CUSTOM_ROLE») annotation, it’s intended for the standard roles (though there’s a mechansim for redefining). But Spring Security has another mechanism – using of the same annotations as @PreAuthorize, @PostFilter: @PreAuthorize(«hasRole(‘ADMINISTRATOR’)»), @PreAuthorize(«hasRole({‘CUSTOMER’, ‘ADMINISTRATOR’})»). You should only specify it in the Spring Security config in the security:global-method-security parameter.

In same way you can use the benefits and opportunities of Spring Security in the view (in JSP). For example:

<%@ taglib prefix="core" uri="http://java.sun.com/jsp/jstl/core" %>
    <%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
    ...
    <sec:authorize access="isAuthenticated()">
        <div id="userBox">
            <span>Welcome, <sec:authentication property="principal.user.firstName"/>!</span>
        </div>
    </sec:authorize>

Such constructions allow not to transfer a model from the controller into the view, but to leave the model extract mechanism for the view (it will request for the model to DAO by itself).

Also you can use the jsp-scriplets on jsp-pages (though there’re getting lots of rivals in scriplets using, basically out of the “bean’s – to bean, caesar’s – to caesar” position, developer is programming, coder and/or designer is working on designing, but this is a moot thing, personally me is not the supporter of either one or the other concept – yes, ugly, yes, sometimes very convenient):

<%@ page import="org.springframework.security.core.context.SecurityContextHolder" %>
    <%@ page import="myproject.auth.AuthUser" %>
    <%	Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        AuthUser authUser = null;
        if (!(principal instanceof String)) authUser = (AuthUser) principal; %>
    ...
    <input type="text" <%= authUser == null ? "" : "disabled=\"disabled\"" %> name="your_name" value="<%= authUser == null ? "" : authUser.getUser().getFirstName()%>"/>
    ...
    <% if (authUser == null) { %>
        <div id="recaptcha_widget">
            <div id="recaptchaContainer">
    ...
            </div>
        </div>
    <% } %>

The above code only reflects the opportunities of the security context usage, but it doesn’t pretend for any meaningful logics.

I want to focus on the “narrow” place caused by the lazy dependency between the authentication object and its parameters (object-Principal): without improvements both bunches of code will call Runtime Exception while opening as the user field (calling of the getUser() method) will contain an object with all the fields by default, filled out as null. Using of the OpenSessionInView pattern without the additional extra-loading of the dependent object will not help in this case as there are different HTTP sessions. Therefore it is necessary either to load the dependent object once at boot o, but it is contrary to the approach because of which the lazy connection has been assigned – the object will be loaded and no change in dependent object will update the downloaded one, in this case it is easier to set the EAGER-connection. I’ve resolved this in authenticationDAO by replacing the basically used sessionFactory.getCurrentSession() for opening a new session: SessionFactoryUtils.openSession(sessionFactory). Perhaps this is not the most economical solution in terms of memory but I haven’t questioned myself yet and didn’t dived in depth for the current problem. I consider that by setting the check for validation of the current session you can refuse from the filter and the OpenSessionInView interceptor, in fact by replacing its work.

There’s a bit more text than you need, there are probably exist questionable or even wrong moments but I have tried to reflect the decision of the difficulties encountered during the implementation of the put-up mechanism.

22
Sep

Deployment automation

Posted by eugene as Web Applications

Automation

In this article I want to show how to automate the deployment process of web-application (WAR archive) to the application Oracle WebLogic 10.3.x server by using Ant.

WebLogic provides several Ant tasks for this case which we’ll use, that’s why we’ll need either pre-installed WebLogicor you can get the necessary libraries from the existing installation. In another article I’ll describe on how to do that.

Getting started

The typical deployment process looks like the following:

  • Verify if the application is installed on the server
  • If the application is installed, it should be removed
  • Install new application

WebLogic has the Ant-task in stock which allows to implement the following actions (http://docs.oracle.com/cd/E14571_01/web.1111/e13706/wldeploy.htm):

  • deploy
  • undeploy
  • redeploy
  • listapps
  • start
  • stop

At the first glance it seems that redeploy is all you need but this solution doesn’t work in case if the application installation onto the server is performed manually via the administrative console. In this case server returns an error that the application is being installed from another path than the installed on the server at the moment.

That’s why I recommend to use the sequential action calls: undeploy and deploy as described below:

<?xml version="1.0" encoding="UTF-8"?>
<project name="WebLogic Deploy" basedir="." default="deploy">
    
<property name="weblogic.application.name" value="MyApplication"/>
    
<property name="weblogic.application.archive" value="Application.war"/>
    
<property name="weblogic.home" value=""/>
    
<property name="weblogic.domain" value="domain"/>
    
<property name="weblogic.adminurl" value="t3s://adminurl:7777"/>
    
<property name="weblogic.targets" value="target"/>
 
    <taskdef name="wldeploy" classname="weblogic.ant.taskdefs.management.WLDeploy">
        <classpath>
            <fileset dir="${weblogic.home}" includes="server/lib/weblogic.jar"/>
        </classpath>
    </taskdef>
 
    <target name="undeploy">
        <wldeploy name="LEO" action="undeploy" adminurl="${weblogic.adminurl}" userconfigfile="weblogic.id" userkeyfile="weblogic.key" targets="${weblogic.targets}"/>
    </target>
 
    <target name="deploy" depends="undeploy">
        <wldeploy name="${weblogic.application.name}" source="${weblogic.application.name}" action="deploy" remote="true" upload="true" adminurl="${weblogic.adminurl}" userconfigfile="weblogic.id" userkeyfile="weblogic.key" targets="${weblogic.targets}"/>
    </target>
</project>

Let’s walk through the parameters:

  • action – the perfomed command (deploy, undeploy, start, stop and so on)
  • name – application name which we install/remove
  • adminurl – URL of the administrative console, but as a protocol we specify not http:// but t3 (or t3s:// if you use https://)
  • user – user name under which we will install/remove applications
  • password – user password
  • targets – the list of server names (node), clusters on which we install the application. The name can be seen in the administrative console (Environment => Servers, the Name column or Cluster)
  • source – path to archive of the installed application
  • upload – flag that tells us that the source application archive needs to be loaded on the server, in another case the archive needs to be uploaded on the server by other ways, for instance, using SCP
  • remote – is the flag which tells us that the application server is installed on another physical server
  • Verification for installed application

    The above scenario is only suitable for situations where the installed application is already located on the server, moreover installed by wideploy rather than manually, via the administrative console. otherwise WebLogic will refuse to install the application. What to do in case of the initial installation of the application?

    To make the installation script working independently of the presence of the installed applicatio it’s necessary to add a check. Then the sequence of actions is as follows:

    • Verify if the application is installed on the server
    • If the application is installed, then remove the previous version
    • Install new version of the application

    What is said that is done! For verifying we’ll use the wlconfig Ant-task with the help of which you can configure the server (for example, create the data sources) and perform different administrative actions, including the list of installed applications.

    The modified Ant-script is represented below:

    <?xml version="1.0" encoding="UTF-8"?>
    <project name="WebLogic Deploy" basedir="." default="deploy">
        
    <property name="weblogic.application.name" value="MyApplication"/>
        
    <property name="weblogic.application.archive" value="Application.war"/>
        
    <property name="weblogic.home" value=""/>
        
    <property name="weblogic.domain" value="domain"/>
        
    <property name="weblogic.adminurl" value="t3s://adminurl:7777"/>
        
    <property name="weblogic.targets" value="target"/>
     
        <taskdef name="wlconfig" classname="weblogic.ant.taskdefs.management.WLConfig">
            <classpath>
                <fileset dir="${weblogic.home}" includes="server/lib/weblogic.jar"/>
            </classpath>
        </taskdef>
     
        <taskdef name="wldeploy" classname="weblogic.ant.taskdefs.management.WLDeploy">
            <classpath>
                <fileset dir="${weblogic.home}" includes="server/lib/weblogic.jar"/>
            </classpath>
        </taskdef>
     
        <target name="check">
            <echo>Checking if application is already deployed</echo>
            <wlconfig url="${weblogic.adminurl}" userconfigfile="weblogic.id" userkeyfile="weblogic.key">
                <query pattern="bwag:Name=MyApplication,Type=Application" property="weblogic.application.installed"/>
            </wlconfig>
            <echo message="${weblogic.application.installed}"/>
        </target>
     
        <target name="undeploy" depends="check" if="weblogic.application.installed">
            <wldeploy name="LEO" action="undeploy" adminurl="${weblogic.adminurl}" userconfigfile="weblogic.id" userkeyfile="weblogic.key" targets="${weblogic.targets}"/>
        </target>
     
        <target name="deploy" depends="undeploy">
            <wldeploy name="${weblogic.application.name}" source="${weblogic.application.name}" action="deploy" remote="true" upload="true" adminurl="${weblogic.adminurl}" userconfigfile="weblogic.id" userkeyfile="weblogic.key" targets="${weblogic.targets}"/>
        </target>
    </project>

    For checking the availability of the installed application with the help of wlconfig, the folllowing query is implemented:

    bwag:Name=MyApplication,Type=Application

    If the application is installed, then the weblogic.application.installed property will be installed by means of which we define if it’s necessary to run the undeploy task or not (see the if property of the undeploy task in the example above).

20
Sep

Apache Maven – Web Application

Posted by eugene as Web Applications

If you aready know what is Maven and you want to build a simple modular web application (if not – you can read the topic and foundations). The theme of this topic is how to configure pom.xml, add a modular to the project, connect the plugins, deploy the Apache Tomcat application server.

Intro

Let’s take for example a simple web application. It consists of modules: model (Entity and Dao classes), service (services), web (servlets). The project and its modules contain its own pom.xml file. Eclipse will serve as an IDE and all is also fair for NetBeans, IDEA. It is assumed that the maven plugin is already added to IDE, the Tomcat server.

Our steps:

  • create the Maven project
  • create the Maven module
  • set-up maven, tomcat
  • deploy on the server

Creation the Maven project

Let’s create Maven Project in our IDE, it will ask to set the options, choose Skip archetype selection, Group id = com.mycompany, Artifact Id = myproject.

Connecting the modules:

<groupId>com.mycompany</groupId>
<artifactId>myproject</artifactId>
<version>0.0.1-SNAPSHOT</version>
<modules>
  <module>model</module>
  <module>service</module>
  <module>web-servlet</module>
</modules>

By default maven will connect JRE version 1.4, we need 1.6, connect the plugin:

<build>
<plugins>
<plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>2.5.1</version>
      <configuration>
        <source>1.6</source>
        <target>1.6</target>
      </configuration>
    </plugin>
  </plugins>
</build>

The module can contain the dependencies of the other libraries, good practice is to specify the dependency version in dependencyManagement of the project, not in pom.xml of the module:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1-b01</version>
    </dependency>
  </dependencies>
</dependencyManagement>

Creation of the Maven module

Right-clicking the project – create Maven Module. In pom.xml of this module we specify the project:

<packaging>war</packaging>
<parent>
  <groupId>com.mycompany</groupId>
  <artifactId>myproject</artifactId>
  <version>0.0.1-SNAPSHOT</version>
</parent>

You can also specify our modules in dependencies (in this case service). Again if you’ve specified the library version in pom.xml you can (and it’s even better) not to specify the version in pom.xml

<dependencies>
  <dependency>
    <groupId>com.mycompany</groupId>
    <artifactId>service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </dependency>
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
</dependency>

Also we’ll need the plugin in order deploy the application on the server by running the Maven-> build coomand in IDE. Let me note the url lines will be different for Tomcat 6 and 7:

<build>
  <finalName>project</finalName>
<plugins>
<plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>tomcat-maven-plugin</artifactId>
      <version>1.1</version>
      <configuration>
        <url>http://localhost:8080/manager/html</url><!-- ??? Tomcat 7 !-->
        <!--<url>http://localhost:8080/manager</url>!--><!-- ??? Tomcat 6 !-->
        <server>tomcatServer</server>
<path>/project</path>
      </configuration>
    </plugin>
  </plugins>
</build>

Configuring Maven, Tomcat

The Maven plugin should know login, Tomcat password in order to connect to the Tomcat manager. Let’s open (if no, create) a file in home directory /.m2/settings.xml, after that do IDE-> Maven-> User Settings-> Update Settings. Here is settings.xml:

<settings>
  <servers>
    <server>
      <id>tomcatServer</id>
      <username>admin</username>
<password>password</password>
    </server>
  </servers>
</settings>

Let’s add rights for the manager in the Tomcat conf/tomcat-users.xml directory:

<tomcat-users>
  <role rolename="manager"/>
  <role rolename="manager-gui"/>
  <role rolename="admin"/>
  <user username="admin" password="password" roles="admin,manager,manager-gui"/>
</tomcat-users>

It should be noted that IDE can start Tomcat with the settings from the workspace or from the Tomcat directory. We chose the second option, so we put the server parameters in IDE – Server Location-> Use Tomcat installation.

Deploy on the server

Let’s run our Tomcat server from IDE, specify the Maven life cycle for the module: module-> Run As-> Maven build, add tomcat:redeploy into the Goals line and run it. Thus the model has deployed on localhost:8080/project/. Everyboday dance and sing. In Eclipse it’s rather convenient to deploy by using the Shift+Alt+X, M keyword.

17
Jun

The note about connection JSTL into JSP

Posted by eugene as Web Applications

In some cases when compiling JSP you can get the following message:

According to TLD or attribute directive in tag file, attribute value does not accept any expressions.

What is the problem and how to resolve it?

This error occurs because the JSP specification uses the JSP 1.2 (and JSTL 1.0), so it does not understand the expression of EL (Expression Language). In order to use the correct version of the specification in your application you need to do the following two things:

1. Refer to the correct specification of the servlet in the deployment descriptor:

<web-app version="2.5"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

2. Specify the correct link to JSTL in JSP-page.
In JSP 1.2:

<%@ taglib uri='http://java.sun.com/jstl/core' prefix='c'%>

In JSP 2.0:

<%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>

Comparison of specification

Version 2.3 2.4 2.5
Deployment schema http://java.sun.com/dtd/web-app_2_3.dtd http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd
Servlet version>2.3 2.4 2.5
JSP Version 1.2 2.0 2.0
JSTL Version 1.0 1.1 1.1
Link to Core JSTL http://java.sun.com/jstl/core http://java.sun.com/jstl/core http://java.sun.com/jstl/core
Tomcat Version 4.x 5.x 6.x
17
Jun

Seven security settings in web.xml

Posted by eugene as Web Applications

There are a lot of articles about how to configure authentication and authorization in the deployment web.xml descriptor. Instead of having to talk once again about how to configure roles, to protect web-resources and to set different types of authentication, let’s look at some common mistakes in the security settings in the web.xml file.

This article is a translation of Article Seven Security (Mis) Configurations in Java web.xml Files.

1. The Error Pages Are Not Configured

By default Java web-applications send detailed error messages directly to the browser. These messages display the server versions, stack trace, in some cases, the Java code pieces are imprinted in the stack-traces. This information is a real boon for hackers to gather information about a potential victim.

Fortunately, it’s very easy to configure web.xml so that instead of the standard pages with the stack-trace returned the user-specified pages. If you use the below configuration, then when an error code 500 occurs, a “good” page will be shown. Similarly, you can configure the display of error pages for the other HTTP status codes (eg, 404).

<error-page>
	<error-code>500</error-code>
	<location>/path/to/error.jsp</location>
</error-page>

In addition, it’s necessary to prohibit the issuance of the pages with the stack-trace in web.xml with the help of the exception-type tag. The page specified by the user should be displayed instead of this page. As can be seen from the example, we specify the type of the Throwable exception. Throwable is the the base class for all exceptions and errors in Java, so this configuration guarantees us that none of the stack trays will go to the user.

<error-page>
	<exception-type>java.lang.Throwable</exception-type>
	<location>/path/to/error.jsp</location>
</error-page>

However, your code can display the stack-trace if you wrote something like this:

<%
	try {
		String s = null;
		s.length();
	} catch (Exception e) {
		// don't do this!
		e.printStackTrace(new PrintWriter(out));
	}
%>

Do not forget to use the “correct” logging in addition to the proper setting of the web.xml deployment descriptor.

2. Authentication and Authorization Bypass

The following code shows how to set up web-based access control so that everything in secure directory should only be available to users with admin role.

<security-constraint>
	<web-resource-collection>
		<web-resource-name>secure</web-resource-name>
		<url-pattern>/secure/*</url-pattern>
		<http-method>GET</http-method>
		<http-method>POST</http-method>
	</web-resource-collection>
	<auth-constraint>
		<role-name>admin</role-name>
	</auth-constraint>
</security-constraint>

It is usually assumed that if there is such a configuration, there only allowed GET and POST requests, but it is not true. By default, any method is valid and the above configuration is not limiting access to the resources by using methods other than GET and POST. In this configuration, only states that if an appeal to the resource is done using GET or POST, it is necessary that the user has been authenticated. Arshan Dabirsiaghi in his article describes the problem and gives examples of how to use the HTTP-HEAD method, or even completely bogus TEST or JUNK methods which are not listed in the web.xml configuration, to bypass authentication and authorization.

Fortunately, the solution to this problem is very simple. Just remove all the http-method elements from web.xml, then the settings will be properly applied to all requests.

3. SSL Is Not Set Up

SSL should be used everywhere, where the transmission of confidential data is carried out. Of course, you can set up SSL on the Web server and calm down on this but you can also configure SSL for the Web application level as soon as the appropriate SSL-keys will be installed on the application server. It’s very simple.

<security-constraint>
	...
	<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
	</user-data-constraint>
</security-constraint>

4. Not Using the Secure Flag

Many sites use SSL for authentication and then go into the non-SSL mode and all communication with the site is implemented over the insecure protocol. This makes the session cookies (such as JSESSIONID) vulnerable to the “capture of the session” attack (session hijacking). To avoid this, you can create cookies with the secure flag which ensures that the browser will not send these cookies via the non-SSL protocol. This flag is put up as follows:

<session-config>
	<cookie-config>
		<secure>true</secure>
	</cookie-config>
</session-config>

5. Not Using the HttpOnly Flag

Cookies can be created with the flag HttpOnly which ensures that they can not be accessed by the client script. This helps to protect you from some of the most common XSS attacks. Put up the flag as follows:

<session-config>
	<cookie-config>
		<http-only>true</http-only>
	</cookie-config>
</session-config>

The HttpOnly flag allowed you to set the useHttpOnly attribute in the Tomcat 5.5 and 6.x versions for the particular application. This attribute is located in the Context item in the server.xml file. By default, this attribute has been disabled in the Tomcat 5.5 and 6.x versions, but the useHttpOnly attribute has a true default value in Tomcat 7. Thus, in Tomcat 7, even if you set flag in web.xml

<http-only>false</http-only>

your JSESSIONID will be HttpOnly as previously if you do not change this behavior in the server.xml file.

6. Using of URL Parameters to Track the Session

The tracking-mode item in the Servlet 3.0 specification allows you to specify if JSESSIONID will be stored in the cookies or it will be passed as the URL-parameter. If the session ID is stored in the URL-parameter, then it can be saved in the browser history on the proxy server, logs, etc. This makes our application more vulnerable to the “capture session” attack. Instead the Servlet 3.0 specification offers us JSESSIONID stored in cookies. This is done using the following configuration:

<session-config>
<tracking-mode>COOKIE</tracking-mode>
</session-config>

7. The Timeout Is Not Set for the Session

Users like the long-live sessions because they are convenient for use. Hackers like the long-live sessions because they give them more time to conduct attacks such as “session capture”, or Cross Site Request Forgery. What to choose – the convenience and security is up to you but when you’ll be confident with the lifetime of the session, you can configure it as follows:

<session-config>
	<session-timeout>15</session-timeout>
</session-config>

In this example, the session will live within 15 minutes of user inactivity. If the session-timeout is not configured, then the Servlet specification requires that the timeout was used which is chosen by the supplier of the container (it’s 30 minutes for Tomcat). If to indicate a negative number or 0 by way of the length of the session life, it will live “forever.” Such an approach is not recommended.

The idle time can also be configured using the setMaxInactiveInterval method of the HttpSession class. In contrast to the session-timeout element this method takes the time value in seconds.

Conclusion

Building and deploying of secure applications requires consideration of the system from different sides. Settings of the runtime as important as the settings of the web-application. If you want to share with your methods of the security settings of web-applications in Java, please leave your comments.