Servlet Controller with duplicate Statement - java

I tend to have this statement
STKUser authenticatedUser = (STKUser) request.getSession().getAttribute("STKUserSession");
in every method of my Classes. authenticatedUser is used for authorization checks/ logic flow. Is this OK or should I be coding this class differently??? Also are there any recommended books that could help improve my coding for Java Classes like the one below, which are used in web applicatons? Most of my Classes looked like the one below.
public class TD0301AssignmentForm extends Form {
private boolean notifyApprover = false;
boolean employeeChange = false;
public TD0301AssignmentForm(TD0301AssignmentDAO dao) {
this.dao = dao;
}
private TD0301Assignment unlockAssignment(HttpServletRequest request) {
STKUser authenticatedUser = (STKUser) request.getSession().getAttribute("STKUserSession");
TD0301Assignment tdas = new TD0301Assignment();
notifyApprover = true;
boolean unlock = false;
try {
// get the original data
tdas = dao.retreive(request.getParameter("calc_num"), request.getParameter("calc_rev"), request.getParameter("calc_dept"), authenticatedUser);
if ("3".equals(tdas.getForm_approve_state()) && authenticatedUser.getBadge().equals(tdas.getOriginator())) {
tdas.setForm_approve_state("1");
notifyApprover = true;
unlock = true;
}
}
public TD0301Assignment updateAssignment(HttpServletRequest request) {
STKUser authenticatedUser = (STKUser) request.getSession().getAttribute("STKUserSession");
....
if (authenticatedUser.getBadge().equals(tdas.getOriginator())) {
//do something
}
EDIT
The TD0301AssignmentForm Class is accessed using these two Classes.
Servlet
TD0301AssignmentDAO dao = new TD0301AssignmentDAO();
TD0301AssignmentForm form = new TD0301AssignmentForm(dao);
TD0301Assignment obj = new TD0301Assignment();
String pkString = "calc_num=" + request.getParameter("calc_num") + "&calc_rev=" + request.getParameter("calc_rev") + "&calc_dept="
+ request.getParameter("calc_dept");
modelMap.put("dbTable", dbTable);
modelMap.put("action", request.getRequestURL());
modelMap.put("reportTitle", "CommitmentReport");
// I think this is the Application Controller Strategy
actionMap.put(null, new ListAction(modelMap, form, "WEB-INF/views/genericList_v.jsp", "WEB-INF/views/genericList_v.jsp"));
actionMap.put("list", new ListAction(modelMap, form, "WEB-INF/views/genericList_v.jsp", "WEB-INF/views/genericList_v.jsp"));
actionMap.put("view", new ViewAction(modelMap, form, obj, "WEB-INF/views/genericView_v.jsp", "WEB-INF/views/genericView_v.jsp"));
actionMap.put("delete", new DeleteAction(modelMap, form, obj, "WEB-INF/views/genericDeleteConfirm_v.jsp", "WEB-INF/views/genericView_v.jsp"));
actionMap.put("sqlConfirmDelete", new DeleteConfirmAction(form, request.getRequestURL() + "?message=Deletion was successful!", request.getRequestURL()
+ "?method=view&" + pkString));
actionMap.put("edit", new EditAction(modelMap, form, obj, "WEB-INF/views/genericEdit_v.jsp", "WEB-INF/views/genericView_v.jsp"));
actionMap.put("sqlUpdate", new UpdateAction(modelMap, form, obj, request.getRequestURL() + "?message=Update was successful!", "WEB-INF/views/genericEdit_v.jsp"));
actionMap.put("new", new NewAction(modelMap, form, "WEB-INF/views/genericAdd_v.jsp"));
actionMap.put("sqlInsert", new InsertAction(modelMap, form, obj, request.getRequestURL() + "?message=Insert was successful!", "WEB-INF/views/genericAdd_v.jsp"));
String op = request.getParameter("method");
ControllerAction action = (ControllerAction) actionMap.get(op);
if (action != null) {
action.service(request, response);
} else {
String url = "WEB-INF/views/errorMessage_v.jsp";
String errMessage = "Operation '" + op + "' not a valid for in '" + request.getServletPath() + "' !!";
request.setAttribute("message", errMessage);
request.getRequestDispatcher(url).forward(request, response);
}
public class EditAction implements ControllerAction {
private Form form;
private Object obj;
private String xPage;
private String yPage;
private HashMap modelMap;
public EditAction(HashMap modelMap, Form form, Object obj, String yPage, String xPage) {
this.form = form;
this.obj = obj;
this.xPage = xPage;
this.yPage = yPage;
this.modelMap = modelMap;
}
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
obj = form.edit(request);
Iterator it = modelMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pairs = (Map.Entry)it.next();
request.setAttribute(pairs.getKey().toString(), pairs.getValue());
}
request.setAttribute("obj", obj);
request.setAttribute("form", form);
if (form.isSucces()) {
RequestDispatcher view = request.getRequestDispatcher(yPage);
view.forward(request, response);
}
else {
RequestDispatcher view = request.getRequestDispatcher(xPage);
view.forward(request, response);
}
}
}

If you find yourself retrieving the same value all the time, you'd probably at least want to abstract it into a method in a base class:
public class BaseForm extends WhateverYouHave {
public STKUser getUser(HttpServletRequest request) {
return request.getSession().getAttribute("STKUserSession");
}
...
}
...
public class AnotherServlet extends BaseForm {
public TD0301Assignment updateAssignment(HttpServletRequest request) {
if (getUser(request).equals(tdas.getOriginator())) {
...
Another, potentially cleaner option depending on your dispatch/instantiation/etc. mechanism would be to inject the value into your forms (if they're not singletons, unclear):
public class AnotherServlet extends BaseForm {
public AnotherServlet(STKUser user) {
this.user = user;
...
}
public TD0301Assignment updateAssignment(HttpServletRequest request) {
if (user.equals(tdas.getOriginator())) {
...
Or provide it as an argument to form methods (if they are):
public TD0301Assignment updateAssignment(STKUser user, HttpServletRequest request) {
if (user.equals(tdas.getOriginator())) {
        ...
It's unfortunate your forms are tied directly to the servlet spec; it's more pleasant to do as much development as possible without that requirement.

Related

Repository Returning Null while attempting Horizontal Scaling of a Service Class

[ISSUE] repo always returns null when I call repo methods, while stepping through, throws null pointer exception. then front end receives
500: Http failure response for http://localhost:4200/api/aiprollout/updatecsv: 500 Internal Server Error
[HAVE TRIED] Adjusting AutoWired and components and service annotations.
[QUESTIONS]
1- Does every repo method need its own service and controller method?
2- Is it okay to create a new service that uses an existing controller?
3- If this new service uses SuperCsv and I create custom CsvCellProcessors, can these cell processors also call the repo? Should these cell processors perform logic? or should it be done else where? What class annotations should these cellProcessors classes have? #Component?
Any advice is greatly appreciated, feel a little lost at this point not even sure what to do.
[CODE]
Controller:
#RestController
#EnableConfigurationProperties({SpoofingConfigurationProperties.class})
#RequestMapping(value = "")
public class AipRolloutController {
private final Logger logger = some logger
private final AipRolloutService AipRolloutService;
private final CsvParserService csvParserService;
#Autowired
public AipRolloutController(AipRolloutService aipRolloutService, CsvParserService csvParserService) {
this.AipRolloutService = aipRolloutService;
this.csvParserService = csvParserService;
}
#PostMapping(value = "/updatecsv", produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public ResponseEntity<?> processCsv(#RequestParam("csvFile") MultipartFile csvFile) throws IOException {
if (csvFile.isEmpty()) return new ResponseEntity(
responceJson("please select a file!"),
HttpStatus.NO_CONTENT
);
csvParserService.parseCsvFile(csvFile);
return new ResponseEntity(
responceJson("Successfully uploaded - " + csvFile.getOriginalFilename()),
new HttpHeaders(),
HttpStatus.CREATED
);
}
Service:
#Service
public class AipRolloutService {
private static final Logger logger = some logger
#Autowired
private AIPRolloutRepository AIPRolloutRepository;
New Csv parser Service
#Service
public class CsvParserService {
#Autowired private AipRolloutService aipRolloutService;
public CsvParserService(AipRolloutService aipRolloutService) {
this.aipRolloutService = aipRolloutService;
}
public void parseCsvFile(MultipartFile csvFile) throws IOException {
CsvMapReader csvMapReader = new CsvMapReader(new InputStreamReader(csvFile.getInputStream()), CsvPreference.STANDARD_PREFERENCE);
parseCsv(csvMapReader);
csvMapReader.close();
}
private void parseCsv(CsvMapReader csvMapReader) throws IOException {
String[] header = csvMapReader.getHeader(true);
List<String> headers = Arrays.asList(header);
verifySourceColumn(headers);
verifyPovColumn(headers);
final CellProcessor[] processors = getProcessors(headers);
Map<String, Object> csvImportMap = null;
while ((csvImportMap = csvMapReader.read(header, processors)) != null) {
CsvImportDTO csvImportDto = new CsvImportDTO(csvImportMap);
if ( activationTypeP(csvImportDto) ){
int mssValue = Integer.parseInt(csvImportDto.getMssValue());
aipRolloutService.updateAipRollout(csvImportDto.getSource(),
csvImportDto.getPov(),
csvImportDto.getActivationType(),
mssValue);
}
}
}
private CellProcessor[] getProcessors(List<String> headers) {
CellProcessor[] processors = new CellProcessor[headers.size()];
int index = 0;
for (String header : headers) {
if (header.contains(SOURCE_ID)) {
processors[index++] = new CsvSourceIdCellParser();
} else if (header.contains(POV)) {
processors[index++] = new CsvPovCellParser();
} else if (header.contains(ACTIVATION_TYPE)) {
processors[index++] = new CsvActivationTypeCellParser();
} else if (header.contains(ACTIVATION_DATE)) {
processors[index++] = new Optional();
} else if (header.contains(DEACTIVATION_DATE)) {
processors[index++] = new Optional();
} else if (header.contains(MSS_VALUE)) {
processors[index++] = new CsvMssValueCellParser();
} else {
processors[index++] = null; // throw exception? wrong header info instead of allowing null?
}
}
return processors;
}
Custom Cell Processor that calls repo and returns null
public class CsvSourceIdCellParser extends CellProcessorAdaptor {
#Autowired AIPRolloutRepository aipRolloutRepository;
public CsvSourceIdCellParser(){ super(); }
// this constructor allows other processors to be chained
public CsvSourceIdCellParser(CellProcessor next){ super(next); }
#Override
public Object execute(Object value, CsvContext csvContext) {
// throws an Exception if the input is null
validateInputNotNull(value, csvContext);
// get rid of description only need first 3 #'s
value = value.toString().substring(0,3);
// check if WH exists
if( aipRolloutRepository.dcExistsInDatabase(value.toString()) )
return value;
else
throw new RuntimeException("Check Warehouse Value, Value Not Found "
+ "Row number: " + csvContext.getRowNumber()
+ " Column number: " + csvContext.getColumnNumber());
}
}
Repository
#Repository
public class AIPRolloutRepository {
private static final Logger logger = LoggerFactory.getLogger(AIPRolloutRepository.class);
#Autowired
JdbcTemplate jdbcTemplate;
public AIPRolloutRepository() {
}
public boolean dcExistsInDatabase(String dc){
// Query for a count saves time and memory, query for distinct saves time and memory on execution
boolean hasRecord =
jdbcTemplate
.query( "select count (distinct '" + dc +"')" +
"from xxcus.XX_AIP_ROLLOUT" +
"where DC = '" + dc + "';",
new Object[] { dc },
(ResultSet rs) -> {
if (rs.next()) {
return true;
}
return false;
}
);
return hasRecord;
}

User that does not have role outlined in RolesAllowed can still invoke method

I've created a custom IdentityStore, in order to intercept authentication requests and assign roles based on the user.
This is purely POC, not production worthy. And the aim is to not use any Spring methods, only standard Java API.
The problem, is that when I authenticate as user/abc123, calling the method shoppingCartService.getOrderList() does not throw an exception even though user does not have the ADMIN role .. why is that?
Custom IdentityStore:
#ApplicationScoped
public class TestIdentityStore implements IdentityStore {
public CredentialValidationResult validate(UsernamePasswordCredential usernamePasswordCredential) {
if (usernamePasswordCredential.compareTo("user", "abc123")) {
return new CredentialValidationResult("user", new HashSet<>(asList("CUSTOMER")));
} else if (usernamePasswordCredential.compareTo("admin", "abc123")) {
return new CredentialValidationResult("admin", new HashSet<>(asList("ADMIN")));
}
return INVALID_RESULT;
}
}
ApplicationConfig:
#BasicAuthenticationMechanismDefinition(
realmName = "file"
)
#ApplicationScoped
#Named
public class ApplicationConfig {}
Servlet:
#WebServlet("/servlet")
#DeclareRoles({ "CUSTOMER", "ADMIN" })
#ServletSecurity(#HttpConstraint(rolesAllowed = {"CUSTOMER", "ADMIN"}))
public class Servlet extends HttpServlet {
private static final long serialVersionUID = 1L;
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String webName = null;
if (request.getUserPrincipal() != null) {
webName = request.getUserPrincipal().getName();
}
response.getWriter().write("web username: " + webName + "\n");
response.getWriter().write("web user has role \"CUSTOMER\": " + request.isUserInRole("CUSTOMER") + "\n");
response.getWriter().write("web user has role \"ADMIN\": " + request.isUserInRole("ADMIN") + "\n");
ShoppingCartService shoppingCartService = new ShoppingCartServiceImpl();
try {
List<OrderItem> items = shoppingCartService.getOrderList();
response.getWriter().write("shoppingCartService.getOrderList() : " + items + "\n");
} catch (Exception e) {
response.getWriter().write("web user does not have access to shoppingCartService.getOrderList();\n");
}
request.logout();
}
}
Interface:
public interface ShoppingCartService {
#RolesAllowed("ADMIN")
List<OrderItem> getOrderList();
}

REST-ful webservice #Context Injection always returns null

I am creating my first Restful web service with Embedded Jetty with authentication and authorization and I have a filter in which I would like to inject a user object (Employee) which then I can retrieve in a service bean using ResteasyProviderFactory.pushContext() the #Context annotation, but whatever I try the object always is null. I would appreciate any kind of help.
#PreMatching
public class AuthenticationHandler implements ContainerRequestFilter {
#Inject private PxCredentialService credentialService;
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
Response faultresponse = createFaultResponse();
String authorization = requestContext.getHeaderString("Authorization");
String[] parts = authorization.split(" ");
if (parts.length != 2 || !"Basic".equals(parts[0])) {
requestContext.abortWith(createFaultResponse());
return;
}
String decodedValue = null;
try {
decodedValue = new String(Base64Utility.decode(parts[1]));
} catch (Base64Exception ex) {
requestContext.abortWith(createFaultResponse());
return;
}
String[] namePassword = decodedValue.split(":");
Employee emp = credentialService.getCredentialsByLoginAndPass(namePassword[0], namePassword[1], true);
if ( emp != null) {
ResteasyProviderFactory.pushContext(Employee.class, emp);
} else {
throw new NullPointerException("False Login");//requestContext.abortWith(Response.status(401).build());
}
}
#Path( "/people" )
public class PeopleRestService implements credentials {
#Inject private PeopleService peopleService;
#Inject private GenericUserRightsUtil genericUserRightsUtil;
#Produces( { "application/json" } )
#GET
public Collection<Person> getPeople(#Context Employee emp) {
Employee emp = (Employee)crc.getProperty("Employee");
return peopleService.getPeople( page, 5 );
}
}
On my understanding, you want an easy way to identify the user who is performing the request in your resource methods. Have you ever considered setting a SecurityContext with a Principal for the request?
In your filter, if the user credentials as valid, do the following
final SecurityContext currentSecurityContext = requestContext.getSecurityContext();
requestContext.setSecurityContext(new SecurityContext() {
#Override
public Principal getUserPrincipal() {
return new Principal() {
#Override
public String getName() {
return username;
}
};
}
#Override
public boolean isUserInRole(String role) {
return true;
}
#Override
public boolean isSecure() {
return currentSecurityContext.isSecure();
}
#Override
public String getAuthenticationScheme() {
return "Basic";
}
});
Your resource method will be like:
#GET
#Path("{id}")
#Produces(MediaType.APPLICATION_JSON)
public Response foo(#PathParam("id") Long id,
#Context SecurityContext securityContext) {
...
}
To get the Principal, use:
Principal principal = securityContext.getUserPrincipal();
String username = principal.getName();

Server Authentication Module forwarding in Glassfish

I found this guide for developing your own Server Authentication Module (SAM) for Glassfish: http://docs.oracle.com/cd/E18930_01/html/821-2418/gizel.html
It seems pretty straightforward to verify some credentials (in HTTP Auth headers for instance), but my question is this:
Can I develop my SAM in such a way that I can forward the user to a specific page if he's not logged in?
Here's the example from the guide:
package tip.sam;
import java.io.IOException;
import java.util.Map;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.message.AuthException;
import javax.security.auth.message.AuthStatus;
import javax.security.auth.message.MessageInfo;
import javax.security.auth.message.MessagePolicy;
import javax.security.auth.message.callback.CallerPrincipalCallback;
import javax.security.auth.message.callback.GroupPrincipalCallback;
import javax.security.auth.message.callback.PasswordValidationCallback;
import javax.security.auth.message.module.ServerAuthModule;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.util.Base64;
public class MySam implements ServerAuthModule {
protected static final Class[]
supportedMessageTypes = new Class[]{
HttpServletRequest.class,
HttpServletResponse.class
};
private MessagePolicy requestPolicy;
private MessagePolicy responsePolicy;
private CallbackHandler handler;
private Map options;
private String realmName = null;
private String defaultGroup[] = null;
private static final String REALM_PROPERTY_NAME =
"realm.name";
private static final String GROUP_PROPERTY_NAME =
"group.name";
private static final String BASIC = "Basic";
static final String AUTHORIZATION_HEADER =
"authorization";
static final String AUTHENTICATION_HEADER =
"WWW-Authenticate";
public void initialize(MessagePolicy reqPolicy,
MessagePolicy resPolicy,
CallbackHandler cBH, Map opts)
throws AuthException {
requestPolicy = reqPolicy;
responsePolicy = resPolicy;
handler = cBH;
options = opts;
if (options != null) {
realmName = (String)
options.get(REALM_PROPERTY_NAME);
if (options.containsKey(GROUP_PROPERTY_NAME)) {
defaultGroup = new String[]{(String)
options.get(GROUP_PROPERTY_NAME)};
}
}
}
public Class[] getSupportedMessageTypes() {
return supportedMessageTypes;
}
public AuthStatus validateRequest(
MessageInfo msgInfo, Subject client,
Subject server) throws AuthException {
try {
String username =
processAuthorizationToken(msgInfo, client);
if (username ==
null && requestPolicy.isMandatory()) {
return sendAuthenticateChallenge(msgInfo);
}
setAuthenticationResult(
username, client, msgInfo);
return AuthStatus.SUCCESS;
} catch (Exception e) {
AuthException ae = new AuthException();
ae.initCause(e);
throw ae;
}
}
private String processAuthorizationToken(
MessageInfo msgInfo, Subject s)
throws AuthException {
HttpServletRequest request =
(HttpServletRequest)
msgInfo.getRequestMessage();
String token =
request.getHeader(AUTHORIZATION_HEADER);
if (token != null && token.startsWith(BASIC + " ")) {
token = token.substring(6).trim();
// Decode and parse the authorization token
String decoded =
new String(Base64.decode(token.getBytes()));
int colon = decoded.indexOf(':');
if (colon <= 0 || colon == decoded.length() - 1) {
return (null);
}
String username = decoded.substring(0, colon);
// use the callback to ask the container to
// validate the password
PasswordValidationCallback pVC =
new PasswordValidationCallback(s, username,
decoded.substring(colon + 1).toCharArray());
try {
handler.handle(new Callback[]{pVC});
pVC.clearPassword();
} catch (Exception e) {
AuthException ae = new AuthException();
ae.initCause(e);
throw ae;
}
if (pVC.getResult()) {
return username;
}
}
return null;
}
private AuthStatus sendAuthenticateChallenge(
MessageInfo msgInfo) {
String realm = realmName;
// if the realm property is set use it,
// otherwise use the name of the server
// as the realm name.
if (realm == null) {
HttpServletRequest request =
(HttpServletRequest)
msgInfo.getRequestMessage();
realm = request.getServerName();
}
HttpServletResponse response =
(HttpServletResponse)
msgInfo.getResponseMessage();
String header = BASIC + " realm=\"" + realm + "\"";
response.setHeader(AUTHENTICATION_HEADER, header);
response.setStatus(
HttpServletResponse.SC_UNAUTHORIZED);
return AuthStatus.SEND_CONTINUE;
// MAYBE SOMETHING HERE?
}
public AuthStatus secureResponse(
MessageInfo msgInfo, Subject service)
throws AuthException {
return AuthStatus.SEND_SUCCESS;
}
public void cleanSubject(MessageInfo msgInfo,
Subject subject)
throws AuthException {
if (subject != null) {
subject.getPrincipals().clear();
}
}
private static final String AUTH_TYPE_INFO_KEY =
"javax.servlet.http.authType";
// distinguish the caller principal
// and assign default groups
private void setAuthenticationResult(String name,
Subject s, MessageInfo m)
throws IOException,
UnsupportedCallbackException {
handler.handle(new Callback[]{
new CallerPrincipalCallback(s, name)
});
if (name != null) {
// add the default group if the property is set
if (defaultGroup != null) {
handler.handle(new Callback[]{
new GroupPrincipalCallback(s, defaultGroup)
});
}
m.getMap().put(AUTH_TYPE_INFO_KEY, ""MySAM");
}
}
}
Yes, you can do that in the validateRequest method.
Here is a simple example:
public AuthStatus validateRequest(MessageInfo messageInfo,
Subject clientSubject,
Subject serviceSubject) throws AuthException {
// clientSubject.getPrincipals() returns the principals
// check this set to know if the user is not logged in
// if the user is not logged in do the following
HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage();
response.sendRedirect("login.html");
}
It might be better to do it inside of a custom LoginModule (if you already know what that is), but I guess this depends on your requirements.
See also:
LoginModule Bridge Profile (JASPIC) in glassfish
Implementing container authentication in Java EE with JASPIC
JAAS for human beings

HttpServletRequestWrapper removed parameter still showing up

I'm trying to filter out a query parameter named 'reason' using a Filter in java/jsp.
Basically, the filter is in place to ensure that a user has entered a 'reason' for viewing a page. If they have not, it needs to redirect them to the 'enter reason' page. Once they have entered a valid reason, they can continue on to the page they requested.
So the basics of it work. However, the 'reason' is sent via a query paremter (i.e. GET parameter). Once the user selects a reason, the reason parameter is being forwarded on to the page they wanted to see. This is a problem, since checking if the reason paremeter exists is one of the main ways the filter determines if the user can move on.
I've tried extending HttpServletRequestWrapper, and overrode a bunch of methods (i.e. getPameter, etc) in an effort to remove the 'reason' parameter. However, I haven't been able to see the parameter get removed. Once the Filter forwards on to the requested page, the 'reason' parameter is always in the query string (i.e. the url in the browser url bar) as a GET parameter.
My filter class looks like:
public final class AccessRequestFilter implements Filter {
public class FilteredRequest extends HttpServletRequestWrapper {
public FilteredRequest(ServletRequest request) {
super((HttpServletRequest)request);
}
#Override
public String getParameter(String paramName) {
String value = super.getParameter(paramName);
if ("reason".equals(paramName)) {
value = null;
}
return value;
}
#Override
public String[] getParameterValues(String paramName) {
String[] values = super.getParameterValues(paramName);
if ("reason".equals(paramName)) {
values = null;
}
return values;
}
#Override
public Enumeration<String> getParameterNames() {
return Collections.enumeration(getParameterMap().keySet());
}
#Override
public Map<String, String[]> getParameterMap() {
Map<String, String[]> params = new HashMap<String, String[]>();
Map<String, String[]> originalParams = super.getParameterMap();
for(Object o : originalParams.entrySet()) {
Map.Entry<String, String[]> pairs = (Map.Entry<String, String[]>) o;
params.put(pairs.getKey(), pairs.getValue());
}
params.remove("reason");
return params;
}
#Override
public String getQueryString() {
String qs = super.getQueryString();
return qs.replaceAll("reason=", "old_reason=");
}
#Override
public StringBuffer getRequestURL() {
String qs = super.getRequestURL().toString();
return new StringBuffer( qs.replaceAll("reason=", "old_reason=") );
}
}
private FilterConfig filterConfig = null;
private static final Logger logger = MiscUtils.getLogger();
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
public void destroy() {
this.filterConfig = null;
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
logger.debug("Entering AccessRequestFilter.doFilter()");
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
HttpSession session = httpRequest.getSession();
boolean canView = false;
long echartAccessTime = 0L;
String demographicNo = "";
String reason = "";
Date current = new Date();
String user_no = (String) session.getAttribute("user");
ProgramProviderDAO programProviderDAO = (ProgramProviderDAO)SpringUtils.getBean("programProviderDAO");
ProgramQueueDao programQueueDao = (ProgramQueueDao)SpringUtils.getBean("programQueueDao");
// Check to see if user has submitted a reason
reason = request.getParameter("reason");
demographicNo = request.getParameter("demographicNo");
Long demographicNoAsLong = 0L;
try {
demographicNoAsLong = Long.parseLong( demographicNo );
} catch (Exception e) {
logger.error("Unable to parse demographic number.", e);
}
if (reason == null) {
// If no reason was submitted, see if user still has time remaining on previous submission (if there was one)
try {
echartAccessTime = (Long)session.getServletContext().getAttribute("echartAccessTime_" + demographicNo);
} catch (Exception e) {
logger.warn("No access time found");
}
if (current.getTime() - echartAccessTime < 30000) {
canView = true;
}
} else if (!reason.equals("")) {
// TODO: validate reason
canView = true;
session.getServletContext().setAttribute("echartAccessTime_" + demographicNo, current.getTime());
String ip = request.getRemoteAddr();
// Log the access request and the reason given for access
LogAction.addLog(user_no, "access", "eChart", demographicNo, ip, demographicNo, reason);
}
if (!canView) {
// Check if provider is part of circle of care
List<Long> programIds = new ArrayList<Long>();
List<ProgramQueue> programQueues = programQueueDao.getAdmittedProgramQueuesByDemographicId( demographicNoAsLong );
if (programQueues != null && programQueues.size() > 0) {
for (ProgramQueue pq : programQueues) {
programIds.add( pq.getProgramId() );
}
List<ProgramProvider> programProviders = programProviderDAO.getProgramProviderByProviderProgramId(user_no, programIds);
if (programProviders != null && programProviders.size() > 0) {
canView = true;
}
}
}
String useNewCaseMgmt;
if((useNewCaseMgmt = request.getParameter("newCaseManagement")) != null ) {
session.setAttribute("newCaseManagement", useNewCaseMgmt);
ArrayList<String> users = (ArrayList<String>)session.getServletContext().getAttribute("CaseMgmtUsers");
if( users != null ) {
users.add(request.getParameter("providerNo"));
session.getServletContext().setAttribute("CaseMgmtUsers", users);
}
}
else {
useNewCaseMgmt = (String)session.getAttribute("newCaseManagement");
}
String requestURI = httpRequest.getRequestURI();
String contextPath = httpRequest.getContextPath();
if (!canView && !requestURI.startsWith(contextPath + "/casemgmt/accessRequest.jsp")) {
httpResponse.sendRedirect(contextPath + "/casemgmt/accessRequest.jsp?" + httpRequest.getQueryString());
return;
}
logger.debug("AccessRequestFilter chainning");
chain.doFilter( new FilteredRequest(request), response);
}
}
The filter is setup to intercept all request and forwards coming into a subdirectory called casemgmt. The filter in web.xml is like:
<filter>
<filter-name>AccessRequestFilter</filter-name>
<filter-class>org.oscarehr.casemgmt.filter.AccessRequestFilter</filter-class>
</filter>
...
<filter-mapping>
<filter-name>AccessRequestFilter</filter-name>
<url-pattern>/casemgmt/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
Anyone have any ideas how I can actually remove the 'reason' parameter?
Wrapping and manipulating the HttpServletRequest in the server side absolutely doesn't magically affect the URL as you see in browser's address bar. That URL stands as-is, as it's the one which the browser used to request the desired resource. The wrapped request would only affect the server side code which is running after the filter on the same request.
If you want to change the URL in browser's address bar, then you should be sending a redirect to exactly the desired URL.
Basically,
if (reasonParameterIsIn(queryString)) {
response.sendRedirect(requestURL + "?" + removeReasonParameterFrom(queryString));
return;
}

Categories