Improving JSF Security Configuration With Secured Managed Beans
2007-10-24 23:37
537 查看
太晚了,有空再看,明天还要上课...
http://blogs.sun.com/enterprisetechtips/entry/improving_jsf_security_configuration_with
Improving JSF Security Configuration With Secured Managed Beans
By Vinicius Senger
Java EE allows you to protect web resources through declarative security, but this approach does not allow you to protect local beans used by servlets and JavaServer Pages (JSPs). Also, although you can protect JavaServer Faces technology (JSF) pages using declarative security, this is often not sufficient.
This tip will show you a way to extend JSF security configuration beyond web pages using managed bean methods.
Introduction
Java EE allows you to protect web pages and other web resources such as files, directories, and servlets through declarative security. In this approach you declare in a
Notice that you identify the resources you want to protect by specifying their URLs in a
Also, although you can protect JSF pages using declarative security, this is often not sufficient. For example, you might want a JSF application to present the same page to users with different roles, but only allow some of those roles to perform specific operations. For instance, you might allow users with all of those roles to read and update data, but allow users with specific roles to create and delete data. In that case, you need a way to extend JSF security beyond web pages.
Additionally, declarative security doesn't check roles during the request processing commonly used by MVC frameworks and JSF. As a result, a managed bean can return any view id even if it's for a protected resource. This can potentially expose protected resources to a role that should not have access to them.
One solution is to use JBoss Seam Web Beans or JSR 299: Web Beans. Web Beans allow you to configure page security, component security, and even Java Persistence Architecture entity security. However, many companies are adopting simpler security solutions without Seam, Spring, EJB, or security-specific frameworks.
The technique covered in this tip demonstrates a simple approach that extends JSF security using annotations in managed beans methods. A sample application accompanies this tip. The code examples in the tip are taken from the source code of the sample application.
Declare the Extended JSF ActionListener and NavigationHandler
To provide managed bean method protection you need to declare the extended JSF
To enable the classes, you declare the following elements inside the
For example, the following code renders a JSF page with a View button and a Delete button.
When the user clicks on the Delete button, a call is made to the
Set Up User Object Providers
By adding a context parameter into
4000
egrate with container/declarative security.
Your Provider: Implement the
Set Up the ContainerUserProvider
The web container provider approach is integrated with declarative security, so it can be used with applications that already use declarative security. Add the following context parameter to set up the default container user provider:
Here is what the default web container user provider class looks like:
Using a SessionUserProvider
If your solution uses a custom security authentication and authorization process, you can provide a user class adapter that implements the given user interface and bind a user object instance into the HTTP Session with the key name "user". This approach works well for legacy Java EE or J2EE applications that don't use declarative security.
Follow these steps to set up your application to use a
Add the following context parameter to the
Create your
Provide page login with a navigation case called login:
Write a login managed bean that checks the user credentials and puts (or not) the user object into the HTTP session.
Running the Sample Code
A sample package accompanies this tip. This sample runs with a
Download the sample package and extract its contents. You should now see a newly extracted directory
Notice that the
Start the NetBeans IDE.
Open the
Select Open Project from the File menu.
Browse to the
Click the Open Project Folder button.
Run
Right click on the
Select Run Project.
Open your browser to the following URL:
You should see a page that contains two buttons: one button invokes an unprotected method. The other button invokes a protected method.
Click on both buttons and see what happens. You'll see that you can run the unprotected method, but the protected method requires you to have a special role.
About the Author
Vinicius Senger is a performance researcher, Java EE architect, and instructor. He started his career at Sun Microsystems and Oracle as independent consultant and official instructor, and later founded Globalcode, a leading Java-related training company in Brazil. Vinicius is a member of the JSF 2.0 Expert Group, the leader of the Global Education and Learning Community, a NetBeans Dream Team Member, and project leader of JAREF, an educational and research framework. He is also a Sun Certified Enterprise Architect and Programmer P1.
http://blogs.sun.com/enterprisetechtips/entry/improving_jsf_security_configuration_with
Improving JSF Security Configuration With Secured Managed Beans
By Vinicius Senger
Java EE allows you to protect web resources through declarative security, but this approach does not allow you to protect local beans used by servlets and JavaServer Pages (JSPs). Also, although you can protect JavaServer Faces technology (JSF) pages using declarative security, this is often not sufficient.
This tip will show you a way to extend JSF security configuration beyond web pages using managed bean methods.
Introduction
Java EE allows you to protect web pages and other web resources such as files, directories, and servlets through declarative security. In this approach you declare in a
web.xmlfile specific web resources and the security roles that can access those resources. For example, based on the following declarations in a
web.xmlfile, only authenticated users who are assigned the
adminsecurity role can access the secured resources identified by the URL pattern
/members.jsf:
<security-constraint>
<display-name>Sample</display-name>
<web-resource-collection>
<web-resource-name>members</web-resource-name>
<description/>
<url-pattern>/members.jsf</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<description/>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<description/>
<role-name>admin</role-name>
</security-role>
Notice that you identify the resources you want to protect by specifying their URLs in a
<url-pattern>element. Unfortunately, because local beans used by servlets and JavaServer Pages (JSP) cannot be mapped to a
<url-pattern>element, you can't use declarative security to protect local beans.
Also, although you can protect JSF pages using declarative security, this is often not sufficient. For example, you might want a JSF application to present the same page to users with different roles, but only allow some of those roles to perform specific operations. For instance, you might allow users with all of those roles to read and update data, but allow users with specific roles to create and delete data. In that case, you need a way to extend JSF security beyond web pages.
Additionally, declarative security doesn't check roles during the request processing commonly used by MVC frameworks and JSF. As a result, a managed bean can return any view id even if it's for a protected resource. This can potentially expose protected resources to a role that should not have access to them.
One solution is to use JBoss Seam Web Beans or JSR 299: Web Beans. Web Beans allow you to configure page security, component security, and even Java Persistence Architecture entity security. However, many companies are adopting simpler security solutions without Seam, Spring, EJB, or security-specific frameworks.
The technique covered in this tip demonstrates a simple approach that extends JSF security using annotations in managed beans methods. A sample application accompanies this tip. The code examples in the tip are taken from the source code of the sample application.
Declare the Extended JSF ActionListener and NavigationHandler
To provide managed bean method protection you need to declare the extended JSF
ActionListenerand
NavigationHandler. These custom classes analyze each user action and check for authentication and authorization.
To enable the classes, you declare the following elements inside the
faces-config.xmlfile:
<!-- JSF-security method-->
<application>
<action-listener>
br.com.globalcode.jsf.security.SecureActionListener
</action-listener>
<navigation-handler>
br.com.globalcode.jsf.security.SecureNavigationHandler
</navigation-handler>
</application>
SecureActionListenerintercepts calls to managed bean methods and checks for annotated method permissions.
NavigationHandlerforwards the user to a requested view if the user has the required credentials and roles.
For example, the following code renders a JSF page with a View button and a Delete button.
<h:form id="sampleSecurity">
<h:commandButton value="View" id="unprotectedButton"
action="#{CustomerCRUD.view}"/>
<h:commandButton value="Delete"
id="protectedButtonprotectedButton"
action="#{CustomerCRUD.delete}"/>
</h:form>
When the user clicks on the Delete button, a call is made to the
CustomerCRUD.deletemethod. The method includes an annotation that declares a required role for the method.
public class CustomerCRUD {
public String view() {
return "view-customer";
}
@SecurityRoles("customer-admin-adv, root")
public String delete() {
System.out.println("I'm a protected method!");
return "delete-customer";
}
...
SecureActionListenerintercepts calls to
CustomerCRUD.deleteand checks for the
customer-admin-advand root permissions.
NavigationHandlerforwards the user to a requested view if the user has the required credentials and roles.
Set Up User Object Providers
By adding a context parameter into
web.xml, you can set up different user object providers, as follows:
ContainerUserProvider: Int
4000
egrate with container/declarative security.
SessionUserProvider: Look up Http session for object named "user".
Your Provider: Implement the
UserProviderinterface:
<context-param>
<param-name>jsf-security-user-provider</param-name>
<param-value>
YourClassImplementsUserProvider
</param-value>
</context-param>
Set Up the ContainerUserProvider
The web container provider approach is integrated with declarative security, so it can be used with applications that already use declarative security. Add the following context parameter to set up the default container user provider:
<context-param>
<param-name>jsf-security-user-provider</param-name>
<param-value>
br.com.globalcode.jsf.security.usersession.ContainerUserProvider
</param-value>
</context-param>
Here is what the default web container user provider class looks like:
public class ContainerUserProvider implements UserProvider {
ContainerUser user = new ContainerUser();
public User getUser() {
if(user.getLoginName()==null ||
user.getLoginName().equals("")) {
return null;
} else {
return user;
}
}
ContainerUserProviderreferences the
ContainerUserclass. Here's what the
ContainerUserclass looks like (some of the code lines are cut to fit the width of the page):
public class ContainerUser implements User {
public String getLoginName() {
if(FacesContext.getCurrentInstance().getExternalContext().
getUserPrincipal()==null) return null;
else return FacesContext.getCurrentInstance().
getExternalContext().getUserPrincipal().toString();
}
public boolean isUserInRole(String roleName) {
return
FacesContext.getCurrentInstance().getExternalContext().
isUserInRole(roleName);
}
Using a SessionUserProvider
If your solution uses a custom security authentication and authorization process, you can provide a user class adapter that implements the given user interface and bind a user object instance into the HTTP Session with the key name "user". This approach works well for legacy Java EE or J2EE applications that don't use declarative security.
Follow these steps to set up your application to use a
SessionUserProvider:
Add the following context parameter to the
web.xmlfile to set up the user provider to look up the HTTP Session for the "user"object:
<context-param>
<param-name>jsf-security-user-provider</param-name>
<param-value>
br.com.globalcode.jsf.security.usersession.SessionUserProvider
</param-value>
</context-param>
Create your
Userclass adapter implementation:
package model;
public class MyUser
implements br.com.globalcode.jsf.security.User {
//Your user instance object
public String getLoginName() {
//your user bridge
return "me";
}
public boolean isUserInRole(String roleName) {
//your user roles bridge
return true;
}
}
Provide page login with a navigation case called login:
//Login page
<h:form id="loginForm">
<h:outputText value="Login:"/>
<h:inputText value="#{LoginMB.userName}">
</h:inputText>
<h:outputText value="Password:"/>
<h:inputText value="#{LoginMB.password}"/>
<h:commandButton value="Login" action="#{LoginMB.login}"/>
<h:messages/>
</h:form>
<navigation-case>
<from-outcome>login</from-outcome>
<to-view-id>/login.xhtml</to-view-id>
</navigation-case>
Write a login managed bean that checks the user credentials and puts (or not) the user object into the HTTP session.
public class LoginMB {
private String userName;
private String password;
@SecurityLogin
public void login() {
//Your login process here...
MyUser user = new MyUser();
HttpSession session =
(HttpSession) FacesContext.getCurrentInstance().
getExternalContext().getSession(false);
session.setAttribute("user", user);
}
}
Running the Sample Code
A sample package accompanies this tip. This sample runs with a
SessionUserProviderand has a very simple user and login page. To install and run the sample:
Download the sample package and extract its contents. You should now see a newly extracted directory
<sample_install_dir>/facesannotations-glassfish, where
<sample_install_dir>is the directory where you installed the sample package. For example, if you extracted the contents to
C:/on a Windows machine, then your newly created directory should be at
C:/facesannotations-glassfish.
Notice that the
faces-config.xmlfile in the expanded sample package contains the declarations for the
SecureActionListenerand
SecureNavigationHandler.
Start the NetBeans IDE.
Open the
facesannotations-glassfishproject as follows:
Select Open Project from the File menu.
Browse to the
facesannotations-glassfishdirectory from the sample application download.
Click the Open Project Folder button.
Run
facesannotations-glassfishas follows:
Right click on the
facesannotations-glassfishnode in the Projects window.
Select Run Project.
Open your browser to the following URL:
http://localhost:8080/facesannotations-glassfish/index.jsf
You should see a page that contains two buttons: one button invokes an unprotected method. The other button invokes a protected method.
Click on both buttons and see what happens. You'll see that you can run the unprotected method, but the protected method requires you to have a special role.
About the Author
Vinicius Senger is a performance researcher, Java EE architect, and instructor. He started his career at Sun Microsystems and Oracle as independent consultant and official instructor, and later founded Globalcode, a leading Java-related training company in Brazil. Vinicius is a member of the JSF 2.0 Expert Group, the leader of the Global Education and Learning Community, a NetBeans Dream Team Member, and project leader of JAREF, an educational and research framework. He is also a Sun Certified Enterprise Architect and Programmer P1.
相关文章推荐
- Spring security 3.1 +JSF 2.0 . problem with annotating methods in ManagedBeans?
- Configure Managed Beans in JSF 2.0
- Injecting Managed beans in JSF 2.0
- Lock down Windows Server 2003 with the Security Configuration Wizard
- jsf、Spring、Hibernate 集成 faces-managed-beans.xml 配置
- WebSPhere: EJBConfigurationException: Using Commit Option A with a workload managed server
- How to reference JSF managed beans which are provided in a JAR file?
- ssh2 整合 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in Servl
- org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'seniorContro
- 解决Error:Configuration with name 'default' not found.
- Tip/Trick: Integrating ASP.NET Security with Classic ASP and Non-ASP.NET URLs
- FAQ(42):org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'bill
- Android: ImageLoader must be init with configuration before using
- Intellij setup with Java configuration
- Sound configuration on Raspberry Pi with ALSA
- Project configuration is not up-to-date with pom.xml
- The virtual machine could not be added. The virtual machine configuration could not be added. A configuration with this name already exists.
- mybatis错误之 Property 'configuration' and 'configLocation' can not specified with together 解决
- Handling Configuration Changes with Fragments