Why doesn't Apache Shiro's [anon] Filter work correctly? - apache

I tried to use authentication with Apache Shiro on my project, but without succes. I can't discover where is the trouble. I need only that whoever user access the page /pages/principal/products.xhtml directly, choose the product to buy and then be redirect to /purchase.xhtml to finish the purchase, but in my case all requests that I try are redirect to /login.xhtml page. Does anyone have any suggestions? code below. thanks!
shiro.ini
[main]
authc.loginUrl = /login.xhtml
authc.successUrl = /index.xhtml
[users]
admin#faces.com = adminfaces, admin
user#faces.com = user, customer
[roles]
admin = *
customer = purchases
[urls]
/index.xhtml = anon
/pages/principal/products = anon
/login.xhtml = authc
/javax.faces.resource/** = anon
/logout = logout
/pages/purchase/** = authc
/protected/** = authc, roles[admin]
web.xml
...
<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>
...

My guess is you need to change the line:
/pages/principal/products = anon to /pages/principal/products.xhtml = anon
You might also be able to use permissive filter too

I was able to solve my trouble. I'm using now redhat PicketLink solution. It's uses a fluent java language to configure paths to secure and it has a lower learnig curve. I'm considering Apache Shiro a great API for security, but I have a little time to learn it. thanks for your helps #Brian Demers.

Related

tomcat 7 web.xml hierarchy - users and roles - java servlet

I'm trying to get familiar with TomEE, or at least TomCat 7 that is used in an older application I'm currently working.
In the tomcat location there is a web.xml. As far as I understood this is used for all servlets that have no own web.xml, right? Or will this be also used for those servlets that have an own one?
Not sure about the hierachy of this configuration files.
Tried to get a basic authentication working for a module that can be assigned by a url like \localhost:8080\AB
The tomcat-users for \localhost:8080\manager is working fine.
But can't get an login for \localhost:8080\AB
I tried modify the web.xml like:
<security-role>
<role-name>users</role-name>
</security-role>
<security-constraint>
<web-resource-collection>
<web-resource-name>basic demo resource</web-resource-name>
<url-pattern>\AB\*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>users</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
But still no login is required for accessing this servlet.
Than I found out, that there is another web.xml in this Java project, which I also tried to modify with the code above.
I know I'm doing something wrong, but don't get what it is right now.
The role "users" was created in tomcat-users.xml and a user is also assigned to that group.
You have define only security constraint not roles. You need to define tomcat user and crossponding roles like.
<tomcat-users>
<role rolename="AB"/> <!-- you have to define all roles -->
<user username="myname" password="mypassword" roles="AB"/>
<!-- you have to assign login and roles -->
</tomcat-users>
The web.xml in the tomcat directory contains the default settings. A webapp can override definitions in its own web.xml.
To access to /AB you need:
to use FORWARD slashes: <url-pattern>/AB/*</url-pattern>
to have a user with role users in your user database
to enter the username and password in the login popup dialog.

Atmosphere websocket disconnected by Tomcat8

As my Apache Tomcat Server (8.0.39) has session timeout at 30 minutes (set in web.xml), I can't seem to get Atmosphere configured right to stop the webocket being disconnected after 30 minutes. Using runtime 2.4.8 and Javascript 2.3.5.
The message I get is:
Websocket closed, reason: This connection was established under an
authenticated HTTP session that has ended. - wasClean: true
Atmosphere: Firing onClose (closed case)
reasonPhrase:"maxReconnectOnClose reached"
I am using both client and server heartbeats. The server sends the heartbeat every 60 seconds, but this does not stop the Tomcat session from timing out at 30 minutes.
I've tried using MAX_INACTIVITY as outlined here:
https://github.com/Atmosphere/atmosphere/issues/2250
<init-param>
<param-name>org.atmosphere.cpr.AtmosphereInterceptor</param-name>
<param-value>o.a.interceptor.IdleResourceInterceptor</param-value>
</init-param>
<init-param>
<param-name>org.atmosphere.cpr.session.maxInactiveInterval</param-name>
<param-value>3600000</param-value>
</init-param>
<init-param>
<param-name>o.a.cpr.CometSupport.maxInactiveActivity</param-name>
<param-value>3600000</param-value>
</init-param>
But this is ignored as well and Tomcat closes the websocket.
Is there some way in Atmosphere to touch the Http Session and stop it from closing my websockets?
Basic setup:
#WebSocketHandlerService(path = "/async/chat", broadcasterCache =
UUIDBroadcasterCache.class)
public class ChatServer extends WebSocketHandlerAdapter {}
Javascript:
request.url = 'async/chat';
request.contentType = 'application/json';
request.transport = 'websocket';
request.fallbackTransport = 'websocket';
request.maxReconnectOnClose = 5;
request.enableProtocol = true;
request.trackMessageLength = true;
request.timeout = 3600000;
request.logLevel = 'debug';
web.xml:
<servlet>
<description>AtmosphereServlet</description>
<servlet-name>AtmosphereServlet</servlet-name>
<servlet-class>org.atmosphere.cpr.AtmosphereServlet</servlet-class>
<init-param>
<param-name>org.atmosphere.cpr.packages</param-name>
<param-value>atnf.jportal.websocket</param-value>
</init-param>
<init-param>
<param-name>org.atmosphere.cpr.AtmosphereInterceptor</param-name>
<param-value>o.a.client.TrackMessageSizeInterceptor</param-value>
</init-param>
<init-param>
<param-name>
o.a.i.HeartbeatInterceptor.clientHeartbeatFrequencyInSeconds
</param-name>
<param-value>120</param-value>
</init-param>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>AtmosphereServlet</servlet-name>
<url-pattern>/async/*</url-pattern>
</servlet-mapping>
By default, the Tomcat installation closed all sessions after a 30 minute period. With the atmosphere websocket implementation, this timeout will also cause all websockets to close, even though the client/server sends a heartbeat using HeartbeatInterceptor.
A mitigation plan was to simply set all sessions to have an infinite timeout in the application web.xml file, but this leaves stale sessions, which can number in the hundreds if not managed manually. After a bit of digging, it seems one can configure atmosphere to set session max inactive interval to -1 when an atmosphere connection exists.
In web.xml:
<init-param>
<param-name>org.atmosphere.cpr.removeSessionTimeout</param-name>
<param-value>true</param-value>
</init-param>
By itself, this does not enable sessions to have an infinite timeout, you also have to enable the listener
<listener>
<listener-class>org.atmosphere.cpr.SessionSupport</listener-class>
</listener>
With the above enabled, each session is assigned the following attribute/properties:
name: atmosphere.session.timeout.restorer
type: org.atmosphere.cpr.SessionTimeoutRestorer
value: SessionTimeoutRestorer[timeout=1800, requestCount=4]
Logging out of the application removes this attribute and assigns a timeout (30min tomcat default setting) to the remaining session*.
Spring Security closes the existing session and creates a new one (with timeout enabled).

How to set up membrane reverse proxy for 2 hosts with common authenication?

I have the following requirement. Please advise on how to set up the proxies.xml properly.
localhost/... user authentication is required from root level down (basically user needs to be authenticated once to access the whole website, which includes the 2 subsystems below)
localhost/subsys1/... all requests under this url should go to host1:8081
localhost/subsys2/... all requests under this url should go to host2:8082
I tried to set up the proxies.xml this way, but it doesn't seem to work.
<router>
<serviceProxy port="80">
<path>/</path>
<basicAuthentication>
<user name="guest" password="guest"/>
</basicAuthentication>
</serviceProxy>
<serviceProxy port="80">
<path>/subsys1</path>
<target host="host1" port="8081"/>
</serviceProxy>
<serviceProxy port="80">
<path>/subsys2</path>
<target host="host2" port="8082"/>
</serviceProxy>
</router>
Thanks,
Denny
I think the basic auth should be placed on the two proxied service as it will do the auth part.If u are trying to do it globally i havent tried it that way and i am not sure that it can be configured as such.
http://www.membrane-soa.org/service-proxy-doc/4.2/interceptors/examples.htm .What i also found usefull is that membrane service proxy is built on spring :-)

Configuring Spring Security for X509 client authentication, it isn't prompting browser for certificate

I'm trying to enable an application to use Client-Auth security with spring. Here's my configuration:
<security:http pattern="/api/**" >
<security:x509 subject-principal-regex="CN=(.*?),"
user-service-ref="x509UserService" />
<security:intercept-url pattern="/api/**" access="IS_AUTHENTICATED_FULLY" requires-channel="https" />
</security:http>
If I don't configure anything within web.xml or tomcat's server.xml, the browser is never prompted to send along a certificate with the request. Consequently, it always return null in in org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter.extractClientCertificate(HttpServletRequest) method.
Is there something special that needs to be configured to have Spring participate in the SSL flow and request the client certificate?
Any help would be appreciated.
If I specify clientAuth='want' in the server.xml connector configuration, this has the undesirable side-effect of prompting everyone for certificates regardless of if they're accessing the /api path.
Similarly, if I specify the login-config and auth-method to be CLIENT-CERT, it also challenges the user, but then I would basically have to duplicate all of the cert checking I'd be doing in spring (or so it would seem).
Depending on your current java and build variety, at the very minimum you would either need to include something similar to the
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>
org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/api/*</url-pattern>
</filter-mapping>
or if you're using Java configuration with spring...
public class SecurityWebApplicationInitializer
extends AbstractSecurityWebApplicationInitializer {
}

Redirecting to two different welcome-pages depending on the users role in Java EE 6/Glassfish

I have implemented FORM based authetication with Glassfish 3.1 + JDBCRealm + MySQL (MD5). I've got only two roles, user and admin. Everything is going great, I can see from the log that authentication is working in both cases as an uset and as an admin (Watch log below)
Q1: Is it possible to make two different index-files so that when user is admin, he/she goes to /admin/index.xhtml and when user is in role user he goes direct to faces/user/index.xhtml?
Q2: Now when I logged in as an user, I can still go to "admin side" with just writting the whole link straight to address field in a browser, why ja how to avoid that?
Q3: When I logged in as a user and I have ONLY faces/admin/index.xhtml in welcome file list, it redirects me to that file even if xml file tells something else, why?
<welcome-file-list>
<welcome-file>faces/admin/index.xhtml</welcome-file> *?? ----> it goes always here, cause it is the first one I think?*
<welcome-file>faces/user/index.xhtml</welcome-file>
</welcome-file-list>
<security-constraint>
<display-name>Admin Pages</display-name>
<web-resource-collection>
<web-resource-name>Protected Admin Area</web-resource-name>
<description/>
<url-pattern>/faces/admin/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
<http-method>HEAD</http-method>
<http-method>PUT</http-method>
<http-method>OPTIONS</http-method>
<http-method>TRACE</http-method>
<http-method>DELETE</http-method>
</web-resource-collection>
<auth-constraint>
<description/>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<display-name>User Pages</display-name>
<web-resource-collection>
<web-resource-name>Protected Users Area</web-resource-name>
<description/>
<url-pattern>/faces/users/*</url-pattern>
<!--url-pattern>/faces/users/index.xhtml</url-pattern-->
<http-method>GET</http-method>
<http-method>POST</http-method>
<http-method>HEAD</http-method>
<http-method>PUT</http-method>
<http-method>OPTIONS</http-method>
<http-method>TRACE</http-method>
<http-method>DELETE</http-method>
</web-resource-collection>
<auth-constraint>
<description/>
<role-name>user</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>JDBCRealm</realm-name>
<form-login-config>
<form-login-page>/faces/loginForm.xhtml</form-login-page>
<form-error-page>/faces/loginError.xhtml</form-error-page>
</form-login-config>
</login-config>
</web-app>
LOG:
FINE: Login module initialized: class com.sun.enterprise.security.auth.login.JDBCLoginModule
FINEST: JDBC login succeeded for: admin groups:[admin, user]
FINE: JAAS login complete.
FINE: JAAS authentication committed.
FINE: Password login succeeded for : admin
FINE: Set security context as user: admin
FINE: [Web-Security] Setting Policy Context ID: old = null ctxID = jdbcrealm/jdbcrealm
FINE: [Web-Security] hasUserDataPermission perm: (javax.security.jacc.WebUserDataPermission GET)
FINE: [Web-Security] hasUserDataPermission isGranted: true
FINE: [Web-Security] Policy Context ID was: jdbcrealm/jdbcrealm
FINE: [Web-Security] Codesource with Web URL: file:/jdbcrealm/jdbcrealm
FINE: [Web-Security] Checking Web Permission with Principals : null
(Edit after myfear's answer)
-----In glassfish-web.xml I have roles like that. If I understood it correctly it means that admin belongs to groups: admin, customer and user. Customer belongs to groups: customer and user and User belongs to group user. Did I understand it correctly?
<security-role-mapping>
<role-name>admin</role-name>
<group-name>admin</group-name>
<group-name>customer</group-name>
<group-name>user</group-name>
</security-role-mapping>
<security-role-mapping>
<role-name>customer</role-name>
<group-name>customer</group-name>
<group-name>user</group-name>
</security-role-mapping>
<security-role-mapping>
<role-name>user</role-name>
<group-name>user</group-name>
</security-role-mapping>
</glassfish-web-app>
Thank you!
Sami
I've just attempted this as part of a University class and here's how I got the functionality I think you're after.
I'm using Netbeans with a Glassfish 4.1.1 server and have already configured the user roles in the servers file realm.
My project has 3 files:
index.xhtml
users/mainmenu.xhtml
admin/mainmenu.xhtml
The welcome page is set to index.xhtml with the following hyperlinks:
<h4>
<a href="/ED-Secure-war/faces/admin/mainmenu.xhtml">
Admin Login
</a>
</h4>
<h4>
<a href="/ED-Secure-war/faces/user/mainmenu.xhtml">
User Login
</a>
</h4>
In my web.xml security section I have the following roles configured
Now because access to each of these is restricted via the user groups, when you click on the hyperlinks on index you'll be prompted to login. If you enter a valid admin login for the admin link you'll be redirected to admin/mainmenu.xhtml, and vice versa for a user login.
A1) Welcome files aren't related to roles. If you need to do any kind of logic for dispatching users, you need to think about using boolean HttpServletRequest.isUserInRole(String role) or something similar to find out in which role the user is in.
A2) That shouldn't happen. You need to check the roles you have in your JDBCRealm. To what I see here, everything is configured the right way.
A3) I am not sure if I understand your remark "XML" file the right way. But welcome-files aren't bound to roles and .. see A1)
Thanks,
M
For your question 1: use the filter from where you can redirect the user to the specific page either userlogin.xhtml or adminlogin.xhtml
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
String userName = SecurityAssociation.getPrincipal().getName();
String userNameSubject = SecurityAssociation.getSubject().toString();
System.out.println("Yeeey! Get me here and find me in the database: " + userName+ " Subject : "+userNameSubject);
filterChain.doFilter(servletRequest, servletResponse);
}