I stuck up with doFilter of HttpServletRequest.
Im trying to replace new URL for that request.
My code is as follows:
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpReq = (HttpServletRequest) req;
HttpServletResponse httpRes = (HttpServletResponse) res;
//If request resources ==> Continue
if(httpReq.getContextPath().startsWith(httpReq.getContextPath()+"/resources")){
chain.doFilter(req, res);
return;
}
HttpSession session = httpReq.getSession();
EmployeeDTO currentEmployee =(EmployeeDTO)session.getAttribute("currentEmployee");
//If dont have session ==> Return login page
if(currentEmployee == null){
String requestURI = "";
requestURI = httpReq.getRequestURI().replace(httpReq.getRequestURI(), httpReq.getContextPath()+ "/login");
System.out.println(requestURI);
//httpRes.reset();
//httpRes.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
//httpRes.setHeader("Location", requestURI);
httpRes.sendRedirect(requestURI);
chain.doFilter(req, res);
return;
}
chain.doFilter(req, res);
return;
}
But the code above is still not working. How can i do for this?
Thanks in advance!
Why do you have to do a chain.doFilter() after setting a redirect response?
private FilterConfig filterConfig;
public void init(FilterConfig config) throws ServletException {
this.filterConfig = config;
}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpReq = (HttpServletRequest) req;
HttpServletResponse httpRes = (HttpServletResponse) res;
HttpSession session = httpReq.getSession();
boolean requestResources = false;
//If request resources ==> Continue
if(httpReq.getContextPath().startsWith(httpReq.getContextPath()+"/resources")){
requestResources = true;
}
if(session != null){
EmployeeDTO currentEmployee =(EmployeeDTO)session.getAttribute("currentEmployee");
}
if(requestResources || currentEmployee != null){
chain.doFilter();
}else if(currentEmployee == null){
String loginURI = //hardcode the loginURI here.
httpRes.sendRedirect(loginURI);
/*alternatively use the following to do an internal forward rather than a redirect
RequestDispatcher rd = filterConfig.getServletContext().getRequestDispatcher(loginURI); //here the loginURI path should not have the context in the url.
rd.forward(servletReq, response);
*/
}
}
I have also refactored your code to remove the redundant and multiple 'return' statements
Related
Hi I have some existing code in my application that use a security filter
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
if (someCondition==TRUE) {
super.doFilter(request, response, chain);
}else{
chain.doFilter(request, response);
}
}
Now I want to redirect the user to a certain URL after the filter flow is completed. I have added the sendRedirect Method like the below example in code, but this is breaking the filter flow in some cases.
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
if (someCondition==TRUE) {
String targetURL = request.getParameter("targetURL");
if(targetURL != null && targetURL != "undefined") {
LOGGER.info("redirecting to this targetURL : " + targetURL);
response.sendRedirect(targetURL);
// this is an internal URL and should be redirected after executing the filter flow
} else {
super.doFilter(request, response, chain);
}
}else{
chain.doFilter(request, response);
}
}
I have a feeling that this is not correct way to redirect the User to an internal URL as it breaks the filter flow. What is correct way of redirecting to URL after filter processing has been completed?
I have the following at the beginning of many methods.
if ((user.privilege & User.Privilege.WRITE) == 0) {
session.setAttribute("alert", "You do not have permission to save.");
return new ModelAndView("redirect:/admin/home");
}
How can I extract this and put it into a separate method that is called before many other controller methods, similar to Ruby on Rails before_action :validate_privilege, [:save, :weekly_report, ...]?
I found this in the docs, but it doesn't give any examples.
https://docs.spring.io/spring-boot/docs/1.5.19.RELEASE/reference/htmlsingle/#boot-features-embedded-container-servlets-filters-listeners
I found a way to do it based on #Deadpool's answer. It seems like it is more complicated than a simple annotation would be.
#Bean
public GenericFilterBean beforeAction() {
String[] actions = new String[]{"/admin/censor", "/admin/weekly-report", "/admin/email-blast-submit"};
return new GenericFilterBean() {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
// System.out.println("requestURI:"+req.getRequestURI());
boolean found = Arrays.stream(actions).anyMatch(req.getRequestURI()::equals);
if (found) {
User user = (User) req.getSession().getAttribute("user");
if (user != null && (user.privilege & User.Privilege.WRITE) == 0) {
req.getSession().setAttribute("alert", "You do not have permission to save.");
HttpServletResponse res = (HttpServletResponse) response;
res.sendRedirect("/admin/home");
return;
}
}
chain.doFilter(request, response);
}
};
}
For the API using OAuth2, I used
#Override
public ResponseEntity<...> delete(Principal principal, #RequestBody ...) throws ApiException {
isAuthorized(principal, "ROLE_USER");
...
/** If not authorized, throw ApiException. */
private void isAuthorized(Principal principal, String role) throws ApiException {
OauthClientDetail cd = userMapper.getOauthClientDetails(principal.getName());
if (cd == null || cd.authorities == null || !cd.authorities.equals(role)) {
throw new ApiException(HttpStatus.UNAUTHORIZED, ...);
}
}
(ApiException, OauthClientDetail (POJO), and UserMapper (MyBatis) are custom classes.)
If you are looking for Filter to check each request for authorization you can use Filter
#Component
public class AuthFilter implements Filter {
#Override
public void doFilter
ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
LOG.info(
"Starting a transaction for req : {}",
req.getRequestURI());
chain.doFilter(request, response);
LOG.info(
"Committing a transaction for req : {}",
req.getRequestURI());
}
// other methods
}
or GenericFilterBean
public class CustomFilter extends GenericFilterBean {
#Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException {
chain.doFilter(request, response);
}
}
You should use Spring Security
http.regexMatcher("/*") --> your base path or sth.
.exceptionHandling()
.and()
.csrf()
.disable();
http.addFilterAfter(authenticationProcessingFilter(),BasicAuthenticationFilter.class);
*#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("INTERCEPTING---");
if(request !=null && request.getParameter("email")!=null){
System.out.println("session is NOT null------");
session = request.getSession();
session.setAttribute("user", request.getParameter("email"));
}else{
try{
if (session==null){
System.out.println("session lost");
}
}catch(IllegalStateException exception){
System.out.println("session expired");
"redirect:http://localhost:8080/web/authservice/fail";
/this is the redirection that i used, and i tried model and view as well but yet it does not work/
}
}
return true;
}
/*in the above method how should I redirect. Its not redirecting...............
Im unable to redirect the after the session expired it gives me a response commit exception. I ve been trying for hours no solution
Please provide a suitable solution */
Use a servlet filter instead, (place it according to you intercepet requirement in your web.xml).
public class CustomRequestFilter implements Filter {
WebApplicationContext springContext;
#Override
public void init(FilterConfig filterConfig) throws ServletException {
springContext = WebApplicationContextUtils.getWebApplicationContext(filterConfig.getServletContext());
}
#Override
public void doFilter(ServletRequest req, ServletResponse response, FilterChain chain) throws IOException, ServletException, LicenseException {
HttpServletRequest request = (HttpServletRequest) req;
if (XXX) {
//forward or redirect as per requirement
request.getRequestDispatcher("/WEB-INF/jsp/errors/SystemError.jsp").forward(request, response);
}
chain.doFilter(request, response);
}
}
I am trying to get my first servlets to work. I have found some similar problems and solutions to them, but it´s not excatly what I would like to do.
This is my login servlet:
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String username=request.getParameter("username");
String password=request.getParameter("password");
if(LoginValidator.validate(username, password)){
HttpSession session = request.getSession();
session.setAttribute("user", username);
session.setMaxInactiveInterval(30*60);
Cookie sessionCookie = new Cookie("sessionKuki", username);
sessionCookie.setMaxAge(30*60);
response.addCookie(sessionCookie);
RequestDispatcher rd=request.getRequestDispatcher("paste.jsp"); //INSTEAD of paste.jsp I would like to get session attribute called uri I set in filter. BUT I when I try to use get attribute, Eclipse says there is no attribute called URI.
rd.forward(request,response);
}
else{
out.print("Sorry username or password error");
RequestDispatcher rd=request.getRequestDispatcher("login.html");
rd.include(request,response);
}
out.close();
}
}
And there is filter that I use to redirect to login page, when user is not signed in:
public class SessionFilter implements Filter{
// private ServletContext context;
public void init(FilterConfig filterConfig) throws ServletException {
//this.context = filterConfig.getServletContext();
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
String uri = req.getRequestURI(); //THERE IS uri of the site from where the user gets redirected to login page
HttpSession session = req.getSession(false);
session.setAttribute("uri", uri); // HERE I TRY to set uri to session attribute. My intention is to use that uri in my login servlet
if(uri.endsWith(".css")) {
chain.doFilter(request, response);
return;
}
if(uri.endsWith(".js")) {
chain.doFilter(request, response);
return;
}
if(session == null && !(uri.endsWith("login.html") || uri.endsWith("login") || uri.endsWith("forgot.jsp") || uri.endsWith("signup.jsp"))){
res.sendRedirect("login.html");
System.out.print("redirecting to login");
}else{
chain.doFilter(request, response);
}
}
public void destroy() {
}
}
Is it even possible, what I am trying to do? How to do it? Is there a better way to do it? I dont want to mix html and script. My intention is that, when user comes to a pages, and trys to get access to somewhere, he is redirected to login page. And after he logs in, he should be redirected to the page he wanted to go at the beginning.
Not sure if this would work but please try doing your filter like this:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
String uri = req.getRequestURI();
HttpSession currentSession = req.getSession(false);
if(uri.endsWith(".css")) {
chain.doFilter(request, response);
return;
}
if(uri.endsWith(".js")) {
chain.doFilter(request, response);
return;
}
if(currentSession == null && !(uri.endsWith("login.html") || uri.endsWith("login") || uri.endsWith("forgot.jsp") || uri.endsWith("signup.jsp"))){
HttpSession newSession = req.getSession();
newSession.setAttribute("uri", uri);
res.sendRedirect("login.html");
System.out.print("redirecting to login");
}else{
chain.doFilter(request, response);
}
}
What i did was create a new session in the filter if the session is null.
I was trying to write a session filter to centralize authorization check in my app engine web app.
My filter looks like this :
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpReq = (HttpServletRequest) request;
HttpServletResponse httpResp = (HttpServletResponse) request;
HttpSession session = httpReq.getSession();
httpReq.setCharacterEncoding("UTF-8");
httpResp.setCharacterEncoding("UTF-8");
httpResp.setContentType("application/json");
Boolean isAuthorized = (Boolean) session.getAttribute("isAuthorized");
if (!isAuthorized || isAuthorized == null) {
httpResp.sendError(HttpServletResponse.SC_UNAUTHORIZED);
} else {
chain.doFilter(request, response);
}
}
But when I'm launching app engine dev server I'm greeted with this exception : "org.mortbay.jetty.request cannot be cast to javax.servlet.http.httpservletresponse". What am I doing wrong?
You are trying to cast "request" object as response.
change as follows
HttpServletResponse httpResp = (HttpServletResponse) response;