How do you make an ATG droplet serve a default oparam - java

In ATG, the Switch droplet will go to the default oparam if none of the other conditions are met.
I have a droplet that I want to behave similarly. You call it on your page and put code inside of oparam conditions. If you don't have an case for the oparam that is returned from your droplet, it should just go to the default.
droplet.java
public void service(DynamoHttpServletRequest request, DynamoHttpServletResponse response)
throws ServletException, IOException
{
String b = (String) request.getParameter("a");
if(b != null && b.equals("c")){
request.serviceLocalParameter("d", request, response);
}else{
request.serviceLocalParameter("e", request, response);
}
}
droplet.jsp
<dsp:droplet name="Droplet">
<dsp:oparam name="d">
<!-- d param was set -->
</dsp:oparam>
<dsp:oparam name="default">
<!-- e, or some other param was set -->
</dsp:oparam>
</dsp:droplet>
I'm somewhat new to ATG, so I might be going about this the wrong way...

If you try and service a non-existent local parameter, the serviceLocalParameter will return false. So all you have to do is check the value returned by serviceLocalParameter(), if it is false, you can service any number of different arbitrary local parameters. In the example below, I service the arbitrary parameter "default" (NOTE: default is ARBITRARY, it could be called anything. If I had an oparam "foo" and an oparam "bar" and an oparam "beh" I could try and service foo, if that failed, I could try and service bar and if that failed I could try and service beh...)
So, applied to your example, the following would do what you want:
droplet.java
public void service(DynamoHttpServletRequest request, DynamoHttpServletResponse response)
throws ServletException, IOException
{
boolean handled = false;
String b = (String) request.getParameter("a");
if(b != null && b.equals("c")){
handled = request.serviceLocalParameter("d", request, response);
}else{
handled = request.serviceLocalParameter("e", request, response);
}
/*
* Did not find a valid parameter, try servicing the
* parameter named "default" instead
*/
if (!handled) {
request.serviceLocalParameter("default", request, response);
}
}
A more simplified version of this for illustrative purposes (with only the code relevant to serving default):
boolean handled = false;
handled = request.serviceLocalParameter("nondefault", request, response);
if (!handled) {
handled = request.serviceLocalParameter("default", request, response);
}

Related

How to get CasToken from server?

I want to do a Cas Authentication from Standalone-Application but it fails on getting the Ticket from server. Can anyone provide me example code for a method that returns the ticket as String so i can use it for the Authentication. As you see the only Parameter should be the URL from the server. Thats waht i have yet(i know casToken is initialized on null an it doesnt work).
protected String getCasTicket(String serviceUrl) {
String casToken = null;
if (casToken == null){
logger.error("Failed to get CAS-Token!");
}else{
logger.info("Got CAS-Token successful!");
}
return casToken;
}
public class CasAuthenticationServlet extends HttpServlet {
...
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// NOTE: The CasAuthenticationToken can also be obtained using
// SecurityContextHolder.getContext().getAuthentication()
final CasAuthenticationToken token = (CasAuthenticationToken) request.getUserPrincipal();
// proxyTicket could be reused to make calls to the CAS service even if the
// target url differs
final String proxyTicket = token.getAssertion().getPrincipal().getProxyTicketFor(targetUrl);
// Make a remote call using the proxy ticket
final String serviceUrl = targetUrl+"?ticket="+URLEncoder.encode(proxyTicket, "UTF-8");
String proxyResponse = CommonUtils.getResponseFromServer(serviceUrl, "UTF-8");
...
}
CasAuthenticationProvider constructs a CasAuthenticationToken including the details contained in the TicketResponse and the GrantedAuthoritys.
Control then returns to CasAuthenticationFilter, which places the created CasAuthenticationToken in the security context.
Cas Example: https://docs.spring.io/spring-security/site/docs/4.2.x/reference/html/sample-apps.html#cas-sample
EDIT:
Please refer https://www.javaworld.com/article/3313114/what-is-a-java-servlet-request-handling-for-java-web-applications.html for creating a servlet

SpringBoot embedded tomcat server reads unicode character in query parameter as null

I have a rest end point designed in spring boot. Tomcat is being used as embedded server. It takes a query parameter.
When I pass query parameter as param1%uFF07 tomcat internally reads parameter as null
When I pass query parameter as param1%FF07 tomcat reads as some character.
tomcat only reads '%' character when followed by two hexadecimal numbers, if u is placed after '%' character tomcat parse parameter as null with message
Character decoding failed. Parameter [name] with value [param1%uFF07]
has been ignored. Note that the name and value quoted here may be
corrupted due to the failed decoding. Use debug level logging to see
the original, non-corrupted values. Note: further occurrences of
Parameter errors will be logged at DEBUG level.
Here is spring boot controller code
#RestController
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
#RequestMapping("/greeting")
public Greeting greeting(#RequestParam(value = "name", required = false) String name) {
return new Greeting(counter.incrementAndGet(), String.format(template, name));
}
}
You are passing % sign in your url, but % is symbol in url, to pass % as it is... you will have to pass %25 then it will work as you expected.
So, if you pass %25uFF07 then it will show you %uFF07 as value.
No need to change anything in application.properties or any kind of settings. I have tested this in my project.
Please feel free to ask for any clarification. Hope It Helps.
I found out a way using filters. Basics about filters could be found over here. We can intercept request query string there and use Tomcat UDecoder class to parse the query string and if any exception is thrown we can show response of 400
public class SimpleFilter implements Filter {
private final UDecoder urlDecoder = new UDecoder();
private final Logger logger = LoggerFactory.getLogger(SimpleFilter.class);
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
String queryString = httpServletRequest.getQueryString();
if (queryString != null) {
ByteChunk byteChunk = new ByteChunk();
byteChunk.setBytes(queryString.getBytes(), 0, queryString.length());
try {
urlDecoder.convert(byteChunk, true);
} catch (IOException ioException) {
logger.error("Hazarduos character found in request parameter.");
httpServletResponse.setStatus(HttpStatus.BAD_REQUEST.value());
return;
}
}
chain.doFilter(request, response);
}
#Override
public void destroy() {
}
}

Session attributes coming as null in filter

Background: I need to create a filter which aims to capture the http response of a servlet whenever it is hit for the first time. Post that on subsequent servlet hit, I need to send the same http response back which i captured earlier. For this, i am saving the servlet response in a text file and send the same as part of response whenever servlet is accessed from second time.
Now, in my application, every screen is painted by 2 servlets. First servlet(for which i am saving http response) sends back basic template along with some dynamic xml data along with xsl name. During load of DHTML response of first servlet, 2nd servlet is called to fetch XSL. As part of security, during first servlet hit, xsl name is added as part of session attribute which is verified when second servlet is called to fetch xsl.
Now, The issue is when i capture http response of first servlet in the filter and re-send the same as part of subsequent hit, session attributes are coming as null in second servlet. (Ques 1: Why?)
Now, to think of the work around, i am adding the session attributes in a concurrenthashmap when I save the http response in the text file. And when the servlet is hit second time, i set the session attributes explicitly and send the response from text file. Now, again, during second servlet hit, these attributes are coming as null. To inspect more, i tried printing the concurrenthashmap in dofilter method. What i observed is that the value of the session attributes are getting null on subsequent servlet hit. (Ques 2: Why?)
public class ServletResponseMocker implements Filter {
private ServletContext context;
private ConcurrentHashMap<String,String> hmURI_FileNameMap=new ConcurrentHashMap<String, String>();
private ConcurrentHashMap<String,List<String>> hmURI_SessionAttrLMap=new ConcurrentHashMap<String, List<String>>();
private String rootPath;
public void init(FilterConfig fConfig) throws ServletException {
this.context = fConfig.getServletContext();
rootPath=System.getProperty("WAR_ROOT_PATH");
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
String uri = req.getRequestURI();
boolean bToBeProcessed = false;
if (uri.startsWith("some/pattern"))
bToBeProcessed = true;
if (bToBeProcessed) {
res.setCharacterEncoding(System.getProperty("CHARSETTYPE"));
OutputStream out = res.getOutputStream();
byte responseContent[] = null;
String filename = null;
if (hmURI_FileNameMap.containsKey(uri)) {
filename = hmURI_FileNameMap.get(uri);
responseContent = Utils.readBytesFromFile(rootPath + "\\somefolder\\"
+ filename);
res.setContentType("text/html;charset=UTF-8");
res.setContentLength(responseContent.length);
HttpSession session = req.getSession(false);
if (session != null) {
if (hmURI_SessionAttrLMap.get(uri) != null)
session.setAttribute("ClientXSL",
hmURI_SessionAttrLMap.get(uri));
}
res.setHeader("X-FRAME-OPTIONS", "SAMEORIGIN");
} else {
filename = uri.substring(uri.lastIndexOf("/") + 1) + ".vdb";
hmURI_FileNameMap.put(uri, filename);
ResponseWrapper wrapper = new ResponseWrapper(res);
chain.doFilter(request, wrapper);
HttpSession session = req.getSession(false);
// This session attribute is set by some filter in chain and is
// always not null here.
List<String> clientXSLList = (List) session
.getAttribute("ClientXSL");
if (clientXSLList != null) {
hmURI_SessionAttrLMap.put(uri, clientXSLList);
}
responseContent = wrapper.getData();
/*Writing data to text file*/
}
out.write(responseContent);
out.flush();
out.close();
} else {
// To identify the 2nd servlet of the screen which is same for all
// screens
if(uri.startsWith("/someother/pattern/com.second.servlet.fetchXSL")){
HttpSession session = req.getSession(false);
if (session != null) {
// Below session attributes always comes as not null during
// fisrst time screen loading. However, comes as null when
// static response is sent for subsequent servlet hit.
List<String> clientXSLList = (List) session
.getAttribute("ClientXSL");
if (clientXSLList != null)
this.context.log("Getting clientXSL list from session:"
+ Arrays.toString(clientXSLList.toArray()));
}
}
chain.doFilter(request, response);
}
public void destroy() {
}
}
Ok Found the issue.
For Ques 1: I overlooked the code present in second servlet. It clears the session attributes whenever it is hit. Therefore when i capture the http response of first servlet being hit second time, session attributes already got null. And hence, they were coming as null in second servlet.
For ques 2: Issue was with my code in filter.
List<String> clientXSLList = (List) session
.getAttribute("ClientXSL");
if (clientXSLList != null) {
hmURI_SessionAttrLMap.put(uri, clientXSLList);
}
The session attributes were added in a list which was added as part of session. And then when i was copying the session attribute, i was not cloning it. Hence, the same getting cleared. To resolve this, now i am creating the clone and then adding it to my concurrenthashmap as below.
ArrayList<String> clientXSLList = (ArrayList<String>) session
.getAttribute("ClientXSL");
if (clientXSLList != null) {
hmURI_SessionAttrLMap.put(uri, clientXSLList.clone());
}

GateIn: a filter for the login servlet

I need to implement some logic before and after the login servlet invoked by my login.jsp.
So I wrote a filter for the url /login to do that. I need to get the user profile for some operations, so I created this LoginFilter class:
public class LoginFilter implements Filter {
private static Logger logger = Logger.getLogger(LoginFilter.class);
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String username = httpRequest.getParameter("username");
String password = httpRequest.getParameter("password");
chain.doFilter(request, response);
PortalRequestContext context = PortalRequestContext.getCurrentInstance();
if (context == null)
logger.info("PortalRequestContext is NULL");
else {
String userId = context.getRemoteUser();
if (userId == null || userId.equals(""))
logger.info("Login failed, IP:" + httpRequest.getRemoteAddr());
else
logger.info("Login executed, username:" + userId);
}
}
The problem is that "context" (PortalRequestContext) is always null. What ma I doing wrong? Is this the right approach?
If you are using GateIn, you can try using
org.exoplatform.portal.webui.util.Util.getPortalRequestContext().getRequest()
ce
You can develop a Valve and add it into Context file of "portal" webapp (Tomcat/conf/Catalina/localhost/portal.xml).
That's what is done in GateIN for SSO extension for example:
See ServletAccessValve
ServletAccess.setRequestAndResponse(request, response);
Then, the Request is accessed in SSOLoginModule using this:
// Tomcat way (Assumed that ServletAccessValve has been configured in context.xml)
else
{
request = ServletAccess.getRequest();
}
For JBoss, it's more simple, you have just to use
javax.security.jacc.PolicyContext.getContext(HttpServletRequest.class.getName())
At login time, PortalRequestContext's not been created yet, but you can get remote user by calling HttpServletRequest#getRemoteUser()
You can add a GateIN Filter like detailed here.
And you can use statically in this Filter the ConversationState to get the current username:
ConversationState.getCurrent().getIdentity().getUserId();
Just use the conversation state object:
// Gets the current user id
ConversationState conversationState = ConversationState.getCurrent();
org.exoplatform.services.security.Identity identity = conversationState.getIdentity();
String userId = identity.getUserId();

how to stop servlet?

I have a servlet that looks like this:
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException{
String param1 = request.getParameter("param1");
String param2 = request.getParameter("param2");
validateInput(param1, param2, request, response);
//if nothing's wrong with the input, do this and that
}
private void validateInput(String param1, String param2, HttpServletRequest request, HttpServletResponse response) throws IOException{
boolean fail = false;
//validate input blah blah blah
if (fail){
PrintWriter out = response.getWriter();
out.write("invalid input");
//end process or servlet
}
}
The idea is that I want to pass param1 and param2 to function validateInput() to validate whether or not the input is valid. If input is invalid, write a message back and then end the process. My question is how to end the process? I'm aware of that calling return; in doPost() will end the process but I'm trying to avoid returning any value from validateInput() to doPost() just for the sake of ending the process. I personally feel that it's more readable this way rather than returning true or false to doPost() and call return; there. Is there a way to do it? Or is it simply impossible?
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException{
String param1 = request.getParameter("param1");
String param2 = request.getParameter("param2");
if(!isValidInput(param1, param2)){
PrintWriter out = response.getWriter();
out.write("invalid input");
return;
}
//if nothing's wrong with the input, do this and that
}
private boolean isValidInput(String param1, String param2){
boolean fail = false;
//validate input and return true/false
}
Control will always return to doPost after validateInput runs unless you throw an exception (either an unchecked exception or IOException in this case).
So if you do not return ANY value from validateInput to doPost, even if you commit the response, doPost will still go on to do whatever it is supposed to do. (Of course, if the response is commited, the browser will be entirely unaware of any further activity on the server side).
You will need to return a value, throw an exception (which doPost may catch) or set a global value that doPost checks (which is just messy).
More sophisticated way would be .
validate and setAttributes to request if error found and forward request to jsp
on jsp check for the error attribute if any present display them
See Also
our Servlet wiki page, it explains it very well with example
What are you calling "the process"? That single request? If yes, then sending a message back DOES end the servlet's responsibility. HTTP is a request/response protocol.
If you mean stopping the servlet, that's not right. The servlet runs in the container, which is still going. It waits for the next request.
I don't see anything that merits stopping. Validation and routing back with errors is common.
Try this:
I changed your validate to return a boolean, so you can run an if statement on it in the doPost method. I also made it return a success instead of failure, just so the check makes more sense once you've returned.
response.sendError will allow you to do a generic error page (See this: http://blogs.atlassian.com/2007/07/responsesenderror_vs_responses/) instead of your output. If you want that you'll want setStatus (again, see the link).
The return should terminate execution and prevent the rest from happening, but it won't shut down the servlet like a system.exit(0) would.
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException{
String param1 = request.getParameter("param1");
String param2 = request.getParameter("param2");
if (! validateInput(param1, param2, request, response)){
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
//Or you can use this instead...
//response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
//PrintWriter out = response.getWriter();
//out.write("invalid input");
return;
}
//if nothing's wrong with the input, do this and that
}
private boolean validateInput(String param1, String param2, HttpServletRequest request, HttpServletResponse response) throws IOException{
boolean success = false;
//validate input blah blah blah
return success;
}
It sounds like you want to get a reference to the OutputStream to write HTML back to the client?
You can make use of response.getOutputStream() that would return a ServletOutputStream.
Once you have written to this stream, you need to finish. You will have to close() and flush() once you are done.
Whatever you write to this stream will be sent to the browser. Also remember to call the
response.setContentType("text/html"); so the browser knows its dealing with HTML.
have you tried with either one of the following
response.sendRedirect("some view.jsp");
(or)
System.exit(0); // which exits from the program

Categories