I use the combination of basic auth and spring security (JWT token) (Springboot)
I have the following setup:
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app 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_3_0.xsd"
version="3.0">
<display-name>det</display-name>
<description>det</description>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<security-constraint>
<web-resource-collection>
<web-resource-name>images</web-resource-name>
<url-pattern>/images/*</url-pattern>
</web-resource-collection>
<!-- OMIT auth-constraint -->
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Entire Application</web-resource-name>
<url-pattern>/login</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>User</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
So the login service returns a JWT token. Then spring security takes over and uses the token to validate the use of rest services.
This all works. I only have one problem. When the user sends wrong credentials I get a 401 error and the popup auth shows up. I want to avoid this. I tried using a filter to change the response code, but it does not seem to be triggered.
How can I solve this.
I found the solution, used an error servlet for 401 errors and removed the WWW-Authenticate value from the response header
Related
I'm working on a project, which uses JSF 2.2 in a "WebSphere Portal" environment.
I am having strange behavior with ViewScoped beans.
Suppose I have two pages in my Portal, one called "A" and one called "B".
On my "A" page there is a portlet that has a screen with a list of Ajax paging items. Suppose I click to go to page 2 in this list of items and I navigate to the "B" page in the Portal.
The expected behavior of a ViewScoped bean is that when we leave the page the bean is destroyed, and when we return the bean is constructed, restarting all the data, that is, losing the state.
However, when I navigate to page "A" again, the current page of the portlet screen pagination is at 2, that is, kept the state, even though I navigated to another page.
WebSphere Portal 9.0
JSF 2.2
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="3.0"
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_3_0.xsd">
<display-name>GSRE-GestaoUsuarios-Portlet</display-name>
<context-param>
<description>
Load JSF runtime when the application server starts up. If this parameter is set to false or removed,
JSF runtime will be loaded and initialized when the first JSF request is processed.
This may disable custom JSF extensions, such as factories defined in the project.</description>
<param-name>com.ibm.ws.jsf.LOAD_FACES_CONFIG_AT_STARTUP</param-name>
<param-value>true</param-value>
</context-param>
<listener>
<listener-class>com.ibm.faces20.portlet.httpbridge.PortletRequestAttributesListener</listener-class>
</listener>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<enabled>true</enabled>
<async-supported>false</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
</web-app>
faces-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="2.0" 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-facesconfig_2_0.xsd">
<application>
<view-handler>com.ibm.faces20.portlet.FaceletPortletViewHandler</view-handler>
<el-resolver>com.ibm.faces20.portlet.PortletELResolver</el-resolver>
<resource-handler>com.ibm.faces20.portlet.httpbridge.PortletResourceHandler</resource-handler>
</application>
<component>
<component-type>com.ibm.faces20.portlet.component.PortletActionURL</component-type>
<component-class>com.ibm.faces20.portlet.component.PortletActionURL</component-class>
</component>
<component>
<component-type>com.ibm.faces20.portlet.component.PortletResourceURL</component-type>
<component-class>com.ibm.faces20.portlet.component.PortletResourceURL</component-class>
</component>
<component>
<component-type>com.ibm.faces20.portlet.component.PortletRenderURL</component-type>
<component-class>com.ibm.faces20.portlet.component.PortletRenderURL</component-class>
</component>
<component>
<component-type>com.ibm.faces20.portlet.component.PortletParam</component-type>
<component-class>com.ibm.faces20.portlet.component.PortletParam</component-class>
</component>
<component>
<component-type>com.ibm.faces20.portlet.component.PortletProperty</component-type>
<component-class>com.ibm.faces20.portlet.component.PortletProperty</component-class>
</component>
<component>
<component-type>com.ibm.faces20.portlet.component.PortletNameSpace</component-type>
<component-class>com.ibm.faces20.portlet.component.PortletNameSpace</component-class>
</component>
<render-kit>
<renderer>
<component-family>javax.faces.Output</component-family>
<renderer-type>com.ibm.faces20.portlet.tag.render.ActionURLTagRender</renderer-type>
<renderer-class>com.ibm.faces20.portlet.tag.render.ActionURLTagRender</renderer-class>
</renderer>
</render-kit>
<render-kit>
<renderer>
<component-family>javax.faces.Output</component-family>
<renderer-type>com.ibm.faces20.portlet.tag.render.ResourceURLTagRender</renderer-type>
<renderer-class>com.ibm.faces20.portlet.tag.render.ResourceURLTagRender</renderer-class>
</renderer>
</render-kit>
<render-kit>
<renderer>
<component-family>javax.faces.Output</component-family>
<renderer-type>com.ibm.faces20.portlet.tag.render.RenderURLTagRender</renderer-type>
<renderer-class>com.ibm.faces20.portlet.tag.render.RenderURLTagRender</renderer-class>
</renderer>
</render-kit>
<render-kit>
<renderer>
<component-family>javax.faces.Output</component-family>
<renderer-type>com.ibm.faces20.portlet.tag.render.PortletNameSpaceTagRender</renderer-type>
<renderer-class>com.ibm.faces20.portlet.tag.render.PortletNameSpaceTagRender</renderer-class>
</renderer>
</render-kit>
</faces-config>
How to make the #ViewScope scope work as expected, ie both page refresh and browser refresh destroy and build the bean.
I have the folder containing a client-side-html-template ("template.xhtml"). The folder resides in public folder (not in WEB_INF).
When saved the file with suffix "xhtml" and wrap the content with "<ui:composition", then client side (ajax) request can access.
However, when I save it to "template.html" and delete the "<ui:composition", then client ajax cannnot access this page (401).
My web.xml has this mapping:
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<mime-mapping>
<extension>xhtml</extension>
<mime-type>text/html</mime-type>
</mime-mapping>
<security-constraint>
<display-name>Restrict raw XHTML Documents</display-name>
<web-resource-collection>
<web-resource-name>XHTML</web-resource-name>
<url-pattern>*.xhtml</url-pattern>
</web-resource-collection>
<auth-constraint />
</security-constraint>
How can I serve common "html-files" by client side ajax request without intercepting these files by jsf/facelets?
Found a simple way without the need to change web.xml:
I changed the static "html" files to "htm".
When trying to logout my application I'm having the following error message :
com.sun.faces.context.FacesFileNotFoundException: /index.xhtml Not Found in ExternalContext as a Resource
To logout I'm going though the following steps inside PhaseListener.beforePhase(PhaseEvent phaseEvent) :
// Redirect to index.html
NavigationHandler nh = fctx.getApplication().getNavigationHandler();
String action_outcome = "/index.html";
nh.handleNavigation(fctx, null, action_outcome);
My web.xml is as follow :
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID"
version="3.0">
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<filter-mapping>
<filter-name>Seam Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>trinidad</filter-name>
<servlet-name>Faces Servlet</servlet-name>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.seam</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<security-constraint>
<display-name>Restrict raw XHTML Documents</display-name>
<web-resource-collection>
<web-resource-name>XHTML</web-resource-name>
<url-pattern>*.xhtml</url-pattern>
</web-resource-collection>
<auth-constraint/>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
</web-app>
I do not have index.xhtml in my app, but I do have and want to keep it index.html file.
Why is my outcome_action given to NavigationHandler rename to index.xhtml ?
How could I avoid it ?
The NavigationHandler expects a JSF page, not a non-JSF page. Moreover, you're there actually not sending a real redirect at all, on the contrary to what the code comment says there. You're just performing a forward here.
Performing a real redirect would be the solution to your problem. It's to be done as below:
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
ec.redirect(ec.getRequestContextPath() + "/index.html");
See also:
What is the difference between redirect and navigation/forward and when to use what?
How to navigate in JSF? How to make URL reflect current page (and not previous one)
Unrelated to the concrete problem, doing authorization job in a phase listener stinks. Have you considered a servlet filter?
See also:
Limitations of using a PhaseListener instead of a Servlet Filter for authorization
Failing to redirect from JSF phaselistener
How to invalidate session in JSF 2.0?
I use Primefaces 4.0 and Shiro 1.2.2 in a website that I currently developed.
My forms are interpreted and Primefaces components are displayed without problem. But when I enable the security on my application, my forms, at least login page, don't displays with Primefaces rendering. I know that Shiro has intercepted all HTTP requests in order to control the access but why my form appears as if I did't use Primefaces? Please, do you have an idea of solution to my problem? Is it possible to integrate Shiro and Primefaces?
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 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_3_0.xsd">
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<welcome-file-list>
<welcome-file>faces/index.xhtml</welcome-file>
</welcome-file-list>
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
<resource-ref>
<res-ref-name>connectionPool</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
<context-param>
<param-name>primefaces.THEME</param-name>
<param-value>redmond</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
</web-app>
shiro.ini:
[main]
authc.loginUrl = /faces/login.xhtml
authc.usernameParam = login:username
authc.passwordParam = login:password
authc.rememberMeParam = login:rememberMe
user.loginUrl = /faces/login.xhtml
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
# Configure JDBC realm password hashing.
redentialsMatcher = org.apache.shiro.authc.credential.HashedCredentialsMatcher
credentialsMatcher.hashAlgorithmName = SHA-256
jdbcRealm.credentialsMatcher = $credentialsMatcher
# Configure JDBC realm SQL queries.
jdbcRealm.authenticationQuery = SELECT password FROM USER WHERE username = ?
dbcRealm.userRolesQuery = SELECT role FROM ROLE WHERE userId = (SELECT id FROM USER WHERE username = ?)
# Configure JDBC realm datasource. DataSource properties
dataSource = org.apache.derby.jdbc.ClientDataSource
dataSource.serverName = localhost
dataSource.portNumber = 1527
dataSource.databaseName = testdb
dataSource.user = admin
dataSource.password = admin
jdbcRealm.dataSource = $dataSource
[users]
admin = password
[urls]
/faces/login.xhtml = authc
/faces/** = authc
I'm a beginner in web development with JSF, Primefaces and Shiro.
Thanks for your help.
Here in the last entry,
[urls]
/faces/login.xhtml = authc
/faces/** = authc
you've told Shiro to authenticate every single unmapped URL matching /faces/**. This thus also covers JSF resources such as CSS/JS/image files which are auto-included by JSF components (as in PrimeFaces). In effects, when the browser wants to download e.g. the CSS file, it receives a login page instead of the actual CSS content and is hence unable to apply the definied CSS styles. You can see it yourself by entering the URL to the CSS file in the browser's address bar yourself. Instead of the CSS file content, you'll see a login page. The webbrowser is "under the covers" facing exactly that problem.
You need to explicitly tell Shiro to allow unauthenticated (anonymous) access to JSF resources. Those resources are identified by an additional /javax.faces.resource path (as definied by the ResourceHandler#RESOURCE_IDENTIFIER constant in JSF API).
[urls]
/faces/login.xhtml = authc
/faces/javax.faces.resource/** = anon
/faces/** = authc
See also:
Apache Shiro in JSF2 tutorial - Restriction in HTTP requests
My problem is similar to:
JSF tags not rendered, JSf tags not being rendered and also JSF tags not being rendered as HTML no suggestion there helped me.
Basically the problem is that regardless of going through a welcome page or not the page is not rendered. IE tries to download the file and chrome basically just skips all the jsf tags. It's obvious that it wasn't translated by the framework but I don't understand why.
The back story is that I did a pilot for a conversion of a system from jsf 1.2 into jsf2. The pilot was successful I managed to get it to work in the pilot branch. However when I'm trying to achieve the same thing for real this time I can't get it to work.
The usual problem seems to be (accordingly to veteran answerer BalusC):
The page URL did not match the url-pattern of the FacesServlet, thus it had not any chance to parse the tags.
OR: The xmlns declarations for JSF components are missing in tag, thus it was treated as plaintext.
The usual fixes seems to be:
Include xmlns in html declaration (I have this in both web.xml and the .xhtml files)
Include or modify Faces Servlet Mapping in web.xml. I can however find no fault in mine. I also tried switching out /faces/* to *.xhtml. Parts that I see as relevant in web.xml included below (Whole file is big, this is a big system):
Part of web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-app_2_5.xsd"
version="2.5">
<context-param>
<description>
Tell the runtime where we are in the project development
lifecycle.
</description>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>com.sun.faces.expressionFactory</param-name>
<param-value>com.sun.el.ExpressionFactoryImpl</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
<url-pattern>*.xhtml</url-pattern>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
<welcome-file-list id="default">
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
</welcome-file-list>
I'm aware that the welcome file is a html file but this worked in the pilot. That file uses
<body bgcolor="#FFFFFF" onload="window.location='portal/login/login.jsf'">
</body>
To get things going. if I manually type the adress in to some random test page containing little and simple code the problem still occurs so the problem feels unrelated to welcome page.
Will gladly assist with any additional information and I'm really stuck here in a bad spot. Thanks for reading.
Resolved by editing faces-config to include xmlns:xsi.