i want session Object not in servlet class but ordinary from we application.
WEB.XML
<listener>
<listener-class>com.abc.web.ApplicationManager</listener-class>
</listener>
<listener>
<listener-class>com.abc.web.SessionManager</listener-class>
</listener>
ViewPrices.java
public class ViewPrices implements Cloneable, Serializable {
Session session = request.getSession();
servletContext.getSession()
anyWay.getSession();
}
call this:
RequestFilter.getSession();
RequestFilter.getRequest();
on your custom filter:
public class RequestFilter implements Filter {
private static ThreadLocal<HttpServletRequest> localRequest = new ThreadLocal<HttpServletRequest>();
public static HttpServletRequest getRequest() {
return localRequest.get();
}
public static HttpSession getSession() {
HttpServletRequest request = localRequest.get();
return (request != null) ? request.getSession() : null;
}
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
if (servletRequest instanceof HttpServletRequest) {
localRequest.set((HttpServletRequest) servletRequest);
}
try {
filterChain.doFilter(servletRequest, servletResponse);
} finally {
localRequest.remove();
}
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void destroy() {
}
}
that you'll register it into your web.xml file:
<filter>
<filter-name>RequestFilter</filter-name>
<filter-class>your.package.RequestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>RequestFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
There are multiple ways to do that, but.. don't. Only your web layer should have access to the session. The other layers should only get the parameters from the session that it needs. For example:
service.doSomeBusinessLogic(
session.getAttribute("currentUser"),
session.getAttribute("foo"));
The options that you have to obtain the request, and from it - the session in a non-servlet class, that is still in the web layer:
store the request in a ThreadLocal in a Filter (and clean it afterwards)
pass it as argument - either in constructor (if the object is instantiated on each request) or as method argument.
I don't think it's possible, to directly access session and request object. What you can do is pass the session and/or request object from servlet to a Java class either in some method or in constructor of the Java class.
Related
I'm developing a custom AuthHandler for our company.
The idea is to allow access based on user and service.
But i can't find a way to access the RegistredService.
Is there a way to pass the RegistredService to my AuthHandler ?
/**
* Mbox Auth Handler
*/
package lu.ion.cas.adaptors.mbox;
import org.jasig.cas.authentication.handler.support.AbstractPreAndPostProcessingAuthenticationHandler;
import org.jasig.cas.authentication.handler.AuthenticationException;
import org.jasig.cas.authentication.principal.Credentials;
import org.jasig.cas.authentication.principal.UsernamePasswordCredentials;
import lu.ion.cas.MboxAuthHelper;
import javax.validation.constraints.NotNull;
public class AuthHandler
extends AbstractPreAndPostProcessingAuthenticationHandler {
private MboxAuthHelper mboxAuthHelper;
private RequestContext context;
protected boolean doAuthentication(final Credentials credentials)
throws AuthenticationException {
return authenticateUsernamePasswordInternal((UsernamePasswordCredentials) credentials);
}
protected boolean authenticateUsernamePasswordInternal(
final UsernamePasswordCredentials credentials)
throws AuthenticationException {
return mboxAuthHelper.load(credentials.getUsername(), credentials.getPassword(), "/auth/check") != null;
}
public boolean supports(Credentials credentials) {
return true;
}
public final void setMboxAuthHelper(final MboxAuthHelper mboxAuthHelper) {
this.mboxAuthHelper = mboxAuthHelper;
}
}
I'm using CAS 3.5.2.
I have used CAS for a few years and found that there are many ways to do everything. I don't know how (or if) you can pass the RegisteredService to your AuthHandler. I solved the same problem by using a custom AuthenticationFilter.
(backend)
Create AuthenticationFilter.java in/near your CAS project like this:
public class AuthenticationFilter implements Filter {
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession();
String loginName = request.getRemoteUser();
String contextPath = request.getContextPath();
System.err.println("loginName is: " + loginName);
System.err.println("contextPath is: " + contextPath);
boolean isAuthorized = false;
// do work/query to find out if they are authorized
if (isAuthorized) {
chain.doFilter(request, response);
} else {
session.invalidate();
// print error page
}
}
#Override
public void init(FilterConfig config) throws ServletException {
}
#Override
public void destroy() {
}
}
(frontend) Then add to your filter chain. If you have a web.xml with existing CAS filters, it is easy.
...
<filter>
<filter-name>Custom Filter</filter-name>
<filter-class>
com.yoursite.filter.AuthenticationFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>Custom Filter</filter-name>
<url-pattern>/index.jsp</url-pattern>
</filter-mapping>
...
No there is no way to do this. If you want to implement authorization rules for CAS 3.5.2, you should review cas-addons:
https://github.com/Unicon/cas-addons/wiki
It is possible to set up #RequestMapping annotation to only allow viewing a page if a session exists? (The user is logged on.)
If you don't want to use spring-security for some reason and want to have your custom implementation to allow access only is session exists, then you could also write a RequestFilter that implements javax.servlet.Filter, and check if the request has a valid session then allow it to go through else show an error page. Here's an example.
public class RequestAuthenticationFilter implements Filter {
private static final Logger LOG = Logger.getLogger(RequestAuthenticationFilter.class);
protected static final List<String> ALLOWED_URL_LIST = Arrays.asList("/login.htm", "/400.htm", "/403.htm", "/404.htm", "/405.htm", "/500.htm", "/503.htm");
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest req, ServletResponse response, FilterChain filterChain) throws IOException,
ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpSession session = request.getSession(false);
String url = (request.getRequestURI());
if(ALLOWED_URL_LIST.contains(url) || url.endsWith(".css") || url.endsWith(".js") || url.endsWith(".png")
|| url.endsWith(".jpg") || url.endsWith(".jpeg") || url.endsWith(".ttf") || url.endsWith(".woff")
|| url.endsWith(".csv")) {
filterChain.doFilter(request, response);
}
else if((null == session) || session.getAttribute("user") == null
|| StringUtils.isEmpty(((User) session.getAttribute("user")).getUsername().trim())) {
((HttpServletResponse) response).sendRedirect("/login.htm");
}
else {
filterChain.doFilter(request, response);
}
}
#Override
public void destroy() {
}
}
In this example the additional check is that if the request is for any image,js,css file then we skip the session check.
Once you have added the filter implementation, you will have to next make sure that all the requests that you want to validate with session go through this Filter. For that you will have to create a bean for this filter and then reference that bean in your web.xml
Here's what you will have to include in your web.xml. Here the is the name with which you create the bean for your filter. And the can be used for deciding which url's you want verified for session check with this filter
<filter>
<filter-name>requestAuthenticationFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>requestAuthenticationFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
You can set it up through Spring-Security fairly easily - for eg. consider a sample configuration from Spring-security site:
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/resources/**", "/signup", "/about").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/db/**").access("hasRole('ROLE_ADMIN') and hasRole('ROLE_DBA')")
.anyRequest().authenticated()
.and()
// ...
.formLogin();
}
here paths mapped with /resources is allowed for everybody(including anonymous users), everything else requires the user to have some role or atleast to have logged in.
I have problems with AccessFilter in java web. When I am calling /main.jspx it redirect to the login.jsp. But when I am trying to log-in some error appeared
public class AccessFilter implements Filter {
private FilterConfig filterConfig;
#Override
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpSession session = ((HttpServletRequest) request).getSession();
HttpServletResponse res = (HttpServletResponse) response;
Client client = (Client) session.getAttribute("client");
if (client != null) {
chain.doFilter(request, response);
} else {
RequestDispatcher dispatcher = request.getRequestDispatcher(
ConfigurationManager.getInstance().getProperty(ConfigurationManager.LOGIN_PAGE_PATH));
dispatcher.forward(request, response);
}
}
#Override
public void destroy() {
this.filterConfig = null;
}
}
web.xml:
<filter>
<filter-name>AccessFilter</filter-name>
<filter-class>ua.kpi.shop.filter.AccessFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AccessFilter</filter-name>
<url-pattern>/jsp/main.jspx</url-pattern>
<url-pattern>/jsp/pokemons.jspx</url-pattern>
</filter-mapping>
Error:
HTTP Status 404 - /PokemonsShop/login.jspx
type Status report
message /PokemonsShop/login.jspx
description The requested resource is not available.
filterConfig.getServletContext().getRequestDispatcher takes the absolute path as opposed to request-getRequestDispatcher. Though whether that is the solution I cannot say.
Two things came into my head when seeing your message:
1) Did you check whether the client object is null or not ? May be when executing the login action (method) you are not setting correctly the client into session ?
2) In the server error, it says "not found /PokemonsShop/login.jspx" but in your filter mapping you are mentioning /jsp/xxx. Would it be because your login page is under the folder jsp and you are redirecting (in the filter) to /PokemonsShop/login.jspx, which should be under webapp root folder to be accessible.
Hope one of them be of help
I am researching and experimenting with a ThreadLocal variable in my Java Web Application. I am using the ThreadLocal variable to store a username (collected from the session) before a request, and then removing it after the request. I have done this by calling a static utility method in a ServletFilter. The reason I do not simply retrieve the username from the session is because I have inherited a system with long-running processes that sometimes take longer to run than the session timeout would allow. My idea is to grab the username before the request is processed and store it in a ThreadLocal variable, thus giving me access to the username throughout the duration of the request even if it takes longer than 15 minutes.
My question is:
Are there any security/performance concerns with this design, and if so, what would be a better solution? Even if there aren't any security and/or performance issues, better ideas are welcome. Snippets from my solution are shown below:
Here is my utility class that would be called in my filter and anywhere that I would need the username.
public abstract class UserUtil {
private static final ThreadLocal<String> threadUser = new ThreadLocal<String>();
public static String getUserId(){
return threadUser.get();
}
public static void setUserId(String userId){
threadUser.set(userId);
}
public static void removeUserId(){
threadUser.remove();
}
}
Here is my servlet filter used to set the username before the request (and clear it via the finally block after the request).
public class UserFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void destroy() {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
try {
HttpServletRequest request = (HttpServletRequest) servletRequest;
UserBean userBean = (UserBean) ((HttpServletRequest) servletRequest).getSession().getAttribute("userBean");
UserUtil.setUserId(userBean.getUserId());
filterChain.doFilter(servletRequest, servletResponse);
} finally{
UserUtil.removeUserId();
}
}
}
Here's my web.xml configuration:
<!--web.xml-->
<web-app>
...
...
...
<filter>
<filter-name>UserFilter</filter-name>
<filter-class>filter.UserFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>UserFilter</filter-name>
<url-pattern>*.jsf</url-pattern>
</filter-mapping>
Any ideas are much appreciated :)
This is actually a fairly common approach for attaching security information to the thread of execution (or any other execution related information).
It is used in Java EE servers internally and by 3rd party code/utils like Spring as well.
It will work just fine.
How can I use a servlet filter to change an incoming servlet request url from
http://nm-java.appspot.com/Check_License/Dir_My_App/Dir_ABC/My_Obj_123
to
http://nm-java.appspot.com/Check_License?Contact_Id=My_Obj_123
?
Update: according to BalusC's steps below, I came up with the following code:
public class UrlRewriteFilter implements Filter {
#Override
public void init(FilterConfig config) throws ServletException {
//
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
String requestURI = request.getRequestURI();
if (requestURI.startsWith("/Check_License/Dir_My_App/")) {
String toReplace = requestURI.substring(requestURI.indexOf("/Dir_My_App"), requestURI.lastIndexOf("/") + 1);
String newURI = requestURI.replace(toReplace, "?Contact_Id=");
req.getRequestDispatcher(newURI).forward(req, res);
} else {
chain.doFilter(req, res);
}
}
#Override
public void destroy() {
//
}
}
The relevant entry in web.xml look like this:
<filter>
<filter-name>urlRewriteFilter</filter-name>
<filter-class>com.example.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>urlRewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
I tried both server-side and client-side redirect with the expected results. It worked, thanks BalusC!
Implement javax.servlet.Filter.
In doFilter() method, cast the incoming ServletRequest to HttpServletRequest.
Use HttpServletRequest#getRequestURI() to grab the path.
Use straightforward java.lang.String methods like substring(), split(), concat() and so on to extract the part of interest and compose the new path.
Use either ServletRequest#getRequestDispatcher() and then RequestDispatcher#forward() to forward the request/response to the new URL (server-side redirect, not reflected in browser address bar), or cast the incoming ServletResponse to HttpServletResponse and then HttpServletResponse#sendRedirect() to redirect the response to the new URL (client side redirect, reflected in browser address bar).
Register the filter in web.xml on an url-pattern of /* or /Check_License/*, depending on the context path, or if you're on Servlet 3.0 already, use the #WebFilter annotation for that instead.
Don't forget to add a check in the code if the URL needs to be changed and if not, then just call FilterChain#doFilter(), else it will call itself in an infinite loop.
Alternatively you can also just use an existing 3rd party API to do all the work for you, such as Tuckey's UrlRewriteFilter which can be configured the way as you would do with Apache's mod_rewrite.
You could use the ready to use Url Rewrite Filter with a rule like this one:
<rule>
<from>^/Check_License/Dir_My_App/Dir_ABC/My_Obj_([0-9]+)$</from>
<to>/Check_License?Contact_Id=My_Obj_$1</to>
</rule>
Check the Examples for more... examples.
A simple JSF Url Prettyfier filter based in the steps of BalusC's answer. The filter forwards all the requests starting with the /ui path (supposing you've got all your xhtml files stored there) to the same path, but adding the xhtml suffix.
public class UrlPrettyfierFilter implements Filter {
private static final String JSF_VIEW_ROOT_PATH = "/ui";
private static final String JSF_VIEW_SUFFIX = ".xhtml";
#Override
public void destroy() {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = ((HttpServletRequest) request);
String requestURI = httpServletRequest.getRequestURI();
//Only process the paths starting with /ui, so as other requests get unprocessed.
//You can register the filter itself for /ui/* only, too
if (requestURI.startsWith(JSF_VIEW_ROOT_PATH)
&& !requestURI.contains(JSF_VIEW_SUFFIX)) {
request.getRequestDispatcher(requestURI.concat(JSF_VIEW_SUFFIX))
.forward(request,response);
} else {
chain.doFilter(httpServletRequest, response);
}
}
#Override
public void init(FilterConfig arg0) throws ServletException {
}
}
In my case, I use Spring and for some reason forward did not work with me, So I did the following:
public class OldApiVersionFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
if (httpServletRequest.getRequestURI().contains("/api/v3/")) {
HttpServletRequest modifiedRequest = new HttpServletRequestWrapper((httpServletRequest)) {
#Override
public String getRequestURI() {
return httpServletRequest.getRequestURI().replaceAll("/api/v3/", "/api/");
}
};
chain.doFilter(modifiedRequest, response);
} else {
chain.doFilter(request, response);
}
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {}
#Override
public void destroy() {}
}
Make sure you chain the modifiedRequest