- Spring Security 3.x Cookbook
- Anjana Mankale
- 960字
- 2021-07-23 14:10:41
JAAS-based security authentication on JSPs
The deployment descriptor is the main configuration file of all the web applications. The container first looks out for the deployment descriptor before starting any application.
The deployment descriptor is an XML file, web.xml
, inside the WEB-INF
folder.
If you look at the XSD of the web.xml
file, you can see the security-related schema.
The schema can be accessed using the following URL: http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd.
The following is the schema element available in the XSD:
<xsd:element name="security-constraint" type="j2ee:security-constraintType"/> <xsd:element name="login-config" type="j2ee:login-configType"/> <xsd:element name="security-role "type="j2ee:security-roleType"/>
Getting ready
You will need the following to demonstrate authentication and authorization:
- JBoss 7
- Eclipse Indigo 3.7
- Create a dynamic web project and name it
Security Demo
- Create a package,
com.servlets
- Create an XML file in the
WebContent
folder,jboss-web.xml
- Create two JSP pages,
login.jsp
andlogoff.jsp
How to do it...
Perform the following steps to achieve JAAS-based security for JSPs:
- Edit the
login.jsp
file with the input fieldsj_username
,j_password
, and submit it toSecurityCheckerServlet
:<%@ page contentType="text/html; charset=UTF-8" %> <%@ page language="java" %> <html > <HEAD> <TITLE>PACKT Login Form</TITLE> <SCRIPT> function submitForm() { var frm = document. myform; if( frm.j_username.value == "" ) { alert("please enter your username, its empty"); frm.j_username.focus(); return ; } if( frm.j_password.value == "" ) { alert("please enter the password,its empty"); frm.j_password.focus(); return ; } frm.submit(); } </SCRIPT> </HEAD> <BODY> <FORM name="myform" action="SecurityCheckerServlet" METHOD=get> <TABLE width="100%" border="0" cellspacing="0" cellpadding="1" bgcolor="white"> <TABLE width="100%" border="0" cellspacing="0" cellpadding="5"> <TR align="center"> <TD align="right" class="Prompt"></TD> <TD align="left"> <INPUT type="text" name="j_username" maxlength=20> </TD> </TR> <TR align="center"> <TD align="right" class="Prompt"> </TD> <TD align="left"> <INPUT type="password"name="j_password" maxlength=20 > <BR> <TR align="center"> <TD align="right" class="Prompt"> </TD> <TD align="left"> <input type="submit" onclick="javascript:submitForm();" value="Login"> </TD> </TR> </TABLE> </FORM> </BODY> </html>
The
j_username
andj_password
are the indicators of using form-based authentication. - Let's modify the
web.xml
file to protect all the files that end with.jsp
. If you are trying to access any JSP file, you would be given a login form, which in turn calls aSecurityCheckerServlet
file to authenticate the user. You can also see role information is displayed. Update theweb.xml
file as shown in the following code snippet. We have used2.5 xsd
. The following code needs to be placed in between thewebapp
tag in theweb.xml
file:<display-name>jaas-jboss</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <security-constraint> <web-resource-collection> <web-resource-name>something</web-resource-name> <description>Declarative security tests</description> <url-pattern>*.jsp</url-pattern> <http-method>HEAD</http-method> <http-method>GET</http-method> <http-method>POST</http-method> <http-method>PUT</http-method> <http-method>DELETE</http-method> </web-resource-collection> <auth-constraint> <role-name>role1</role-name> </auth-constraint> <user-data-constraint> <description>no description</description> <transport-guarantee>NONE</transport-guarantee> </user-data-constraint> </security-constraint> <login-config> <auth-method>FORM</auth-method> <form-login-config> <form-login-page>/login.jsp</form-login-page> <form-error-page>/logoff.jsp</form-error-page> </form-login-config> </login-config> <security-role> <description>some role</description> <role-name>role1</role-name> </security-role> <security-role> <description>packt managers</description> <role-name>manager</role-name> </security-role> <servlet> <description></description> <display-name>SecurityCheckerServlet</display-name> <servlet-name>SecurityCheckerServlet</servlet-name> <servlet-class>com.servlets.SecurityCheckerServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>SecurityCheckerServlet</servlet-name> <url-pattern>/SecurityCheckerServlet</url-pattern> </servlet-mapping>
- JAAS Security Checker and Credential Handler: Servlet is a security checker. Since we are using JAAS, the standard framework for authentication, in order to execute the following program you need to import
org.jboss.security.SimplePrincipal
andorg.jboss.security.auth.callback.SecurityAssociationHandle
and add all the necessary imports. In the followingSecurityCheckerServlet
, we are getting the input from the JSP file and passing it to theCallbackHandler
.We are then passing the Handler object to the
LoginContext
class which has thelogin()
method to do the authentication. On successful authentication, it will createSubject
andPrincipal
for the user, with user details. We are using iterator interface to iterate theLoginContext
object to get the user details retrieved for authentication.In the
SecurityCheckerServlet
Class:package com.servlets; public class SecurityCheckerServlet extends HttpServlet { private static final long serialVersionUID = 1L; public SecurityCheckerServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { char[] password = null; PrintWriter out=response.getWriter(); try { SecurityAssociationHandler handler = new SecurityAssociationHandler(); SimplePrincipal user = new SimplePrincipal(request.getParameter("j_username")); password=request.getParameter("j_password").toCharArray(); handler.setSecurityInfo(user, password); System.out.println("password"+password); CallbackHandler myHandler = new UserCredentialHandler(request.getParameter("j_username"),request.getParameter("j_password")); LoginContext lc = new LoginContext("other", handler); lc.login(); Subject subject = lc.getSubject(); Set principals = subject.getPrincipals(); List l=new ArrayList(); Iterator it = lc.getSubject().getPrincipals().iterator(); while (it.hasNext()) { System.out.println("Authenticated: " + it.next().toString() + "<br>"); out.println("<b><html><body><font color='green'>Authenticated: " + request.getParameter("j_username")+"<br/>"+it.next().toString() + "<br/></font></b></body></html>"); } it = lc.getSubject().getPublicCredentials(Properties.class).iterator(); while (it.hasNext()) System.out.println(it.next().toString()); lc.logout(); } catch (Exception e) { out.println("<b><font color='red'>failed authenticatation.</font>-</b>"+e); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
Create the
UserCredentialHandler
file:package com.servlets; class UserCredentialHandler implements CallbackHandler { private String user, pass; UserCredentialHandler(String user, String pass) { super(); this.user = user; this.pass = pass; } @Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (int i = 0; i < callbacks.length; i++) { if (callbacks[i] instanceof NameCallback) { NameCallback nc = (NameCallback) callbacks[i]; nc.setName(user); } else if (callbacks[i] instanceof PasswordCallback) { PasswordCallback pc = (PasswordCallback) callbacks[i]; pc.setPassword(pass.toCharArray()); } else { throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback"); } } } }
In the
jboss-web.xml
file:<?xml version="1.0" encoding="UTF-8"?> <jboss-web> <security-domain>java:/jaas/other</security-domain> </jboss-web>
Other
is the name of the application policy defined in thelogin-config.xml
file.All these will be packed in as a
.war
file. - Configuring the JBoss Application Server. Go to
jboss-5.1.0.GA\server\default\conf\login-config.xml
in JBoss. If you look at the file, you can see various configurations for database LDAP and a simple one using the properties file, which I have used in the following code snippet:<application-policy name="other"> <!-- A simple server login module, which can be used when the number of users is relatively small. It uses two properties files: users.properties, which holds users (key) and their password (value). roles.properties, which holds users (key) and a comma-separated list of their roles (value). The unauthenticatedIdentity property defines the name of the principal that will be used when a null username and password are presented as is the case for an unauthenticated web client or MDB. If you want to allow such users to be authenticated add the property, e.g., unauthenticatedIdentity="nobody" --> <authentication> <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required"/> <module-option name="usersProperties">users.properties</module-option> <module-option name="rolesProperties">roles.properties</module-option> <module-option name="unauthenticatedIdentity">nobody</module-option> </authentication> </application-policy>
- Create the
users.properties
file in the same folder. The following is theUsers.properties
file with username mapped with role.User.properties
anjana=anjana123
roles.properties
anjana=role1
- Restart the server.
Tip
Downloading the example code
You can download the example code files for all Packt books you have purchased from your account at http://www.PacktPub.com. If you purchased this book elsewhere, you can visit http://www.PacktPub.com/support and register to have the files e-mailed directly to you.
How it works...
JAAS consists of a set of interfaces to handle the authentication process. They are:
- The
CallbackHandler
andCallback
interfaces - The
LoginModule
interface LoginContext
The CallbackHandler
interface gets the user credentials. It processes the credentials and passes them to LoginModule
, which authenticates the user.
JAAS is container specific. Each container will have its own implementation, here we are using JBoss application server to demonstrate JAAS.
In my previous example, I have explicitly called JASS interfaces.
UserCredentialHandler
implements the CallbackHandler
interfaces.
So, CallbackHandler
s are storage spaces for the user credentials and the LoginModule
authenticates the user.
LoginContext
bridges the CallbackHandler
interface with LoginModule
. It passes the user credentials to LoginModule
interfaces for authentication:
CallbackHandler myHandler = new UserCredentialHandler(request.getParameter("j_username"),request.getParameter("j_password")); LoginContext lc = new LoginContext("other", handler); lc.login();
The web.xml
file defines the security mechanisms and also points us to the protected resources in our application.
The following screenshot shows a failed authentication window:
The following screenshot shows a successful authentication window:
See also
- The JAAS-based security authentication on servlet recipe
- The Container-based basic authentication on servlet recipe
- The Form-based authentication on servlet recipe
- The Form-based authentication with open LDAP and servlet recipe
- The Hashing/Digest Authentication on servlet recipe
- The Basic authentication for JAX-WS and JAX-RS recipe
- The Enabling and disabling the file listing recipe