class variable set to null outside of a servlet - servlets

I wrote a simple servlet, in the doPost I got the user name and the password from a jspand authenticated the user by sending the password entered by the user to the data base(mysql). I got the data correctly and I am redirecting the user to another jsp page called welcome.jsp.
my question is , I wrote this method public String getUser(){return userNmae;}; I put it outside of the dopost method, however it is returning null. I have declared the variable userNmae as a class variable and when I debug , the variable contains a value in the dopost method , but it is null outside of the dopost method.why it is null outside of the dopost method?
I am calling getUser() method in the welcome.jsp page.
here is my code
public class UIclass extends HttpServlet {
public UIclass() { };
private String passWord = null;
private String userNmae = null;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("userName");
String password = request.getParameter("password");
Connection connection = null;
try {
connection = Connections.getConnection();
java.sql.PreparedStatement statement = connection.prepareStatement("SELECT PASSWORD,USERNAME FROM LOGIN where username =?");
statement.setString(1, name);
ResultSet resultset = statement.executeQuery();
while (resultset.next()) {
passWord = resultset.getString("PASSWORD");
userNmae = resultset.getString("USERNAME");
}
} catch (Exception e) {
// TODO: handle exception
} finally {
if (connection != null)
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
};
}
if (passWord.equalsIgnoreCase(password)) {
RequestDispatcher rd = request.getRequestDispatcher("welcome.jsp");
rd.forward(request, response);
}
}
public String getUser() {
return userNmae;
}
}

I'll answer by giving you a simpler example of what your code is actually doing:
Bottle bottle1 = new Bottle();
bottle1.setMessage("Hi there");
Bottle bottle2 = new Bottle();
System.out.println(bottle2.getMessage());
What would you expect this program to display? I would expect null, because you set a message on bottle1, and read the message from bottle2. These are two different bottles. When you put a message in a bottle, the message is in that bottle, not in the other bottles.
Your code does the same thing.
The servlet container creates an instance (unique) of UIclass. This is equivalent to creating the first bottle in my example.
The servlet is invoked when you send an HTTP request. It sets the user attribute in the servlet. This is equivalent to bottle1.setMessage("Hi there") in my example.
The container executes your JSP, which contains the code
<jsp:useBean id="uiclass" class="com.servlet.UIclass" scope="request">
This creates a new UIClass instance. It is equivalent to creating the second bottle in my example.
The JSP calls uiclass.getUser(). This is equivalent to getting the message from the second bottle in my example.
There are many, many things wrong in your code:
You shouldn't use scriptlets, and jsp:useBean tags
You should never create instances of servlets by yourself. A servlet is meant to be instanciated and called by the container.
You should realize that a unique servlet instance is called to serve, concurrently, all the requests of all the users to this servlet URL. Storing user-specific data in servlet attributes is thus really wrong
You probably want the user name to be available for all the subsequent requests of this user. That's what the HTTP session is for. You should store the user as an attribute of the HTTP session: request.getSession().setAttribute("userName", userName)
The JSP should use the JSP EL and the JSTL to access beans stored in the request or the session by the servlet:
<c:out value="${userName}"/>

Related

Issue with mvc:annotation-driven and #PathVariable

Not sure what I am doing wrong here but when I DO NOT define the mvc:annotation-driven in my servlet, the value returned from the #PathVariable is not getting displayed in my jsp page and when I do define the annotation-driven, all other links e.g. home gets broken and I get the The specified HTTP method is not allowed for the requested resource (Request method GET not supported).
#Controller("HealthCheckController")
#RequestMapping("/healthCheckSummary")
public class HealthCheckController {
private Log log = LogFactory.getLog(GolSimpleMappingExceptionResolver.class);
private HealthCheckService healthCheckService = null;
private IEappDataAccessFacade dataAccessFacade;
#RequestMapping(value = "/{username}/{password}", method = RequestMethod.GET)
public String getEappStatus(#PathVariable String username, #PathVariable String password, Model model){
String dbConnectivityStatus = getDatabaseConnectivityStatus() ? "online" : "offline";
if (!username.equals("lola") || !password.equals("123")) {
// wrong credentials were provided
log.error("The login credentials in the header are not valid." + username + password);
throw new RuntimeException( "Unable to continue, the login credentials in the header are not valid." + username + password);
}
model.addAttribute("healthCheckSummary", dbConnectivityStatus);
return "healthCheckSummary";
}
public HealthCheckService getHealthCheckService()
{
return healthCheckService;
}
public boolean getDatabaseConnectivityStatus() {
String result = “OK”;
if (result != null) {
return true;
}
return false;
}
}
Oh and in the application context we have defined the
<tx:annotation-driven />
JSP page
<%# page language="java"%>
Welcome ${username} - ${password}
Eapp is currently ${healthCheckSummary}
Two things:
You never put your username and password #PathVariables in the model. Your jsp page has no way of knowing that they even existed as you lose any reference to them after the code leaves getEappStatus. Add the following to your handler method:
model.addAttribute("username", username);
model.addAttribute("password", password);
and see if that works.
You might want to add <mvc:annotation-driven/> just to avoid some surprises when you use some spring-mvc annotations. This isn't strictly necessary, but might save you some head scratching when some #RequestBody doesn't work.

Service Stack:Type definitions should start with a '{', expecting serialized type 'AuthResponse', got string starting with

i am using the following code to athenticate the user using ServiceStack basic auth provider in my asp.net application and receiving serilization exception.Please answer if anyone has solve this problem.Thank you.
I am using the following code in my asp.net application:
<asp:Button ID="btnAuth" runat="server" OnClick="btnAuth_Click" Text="Authenticate"/>
I am recieving exception on clien.Post method in code behind file.
protected void btnAuth_Click(object sender, EventArgs e)
{
try
{
var baseUrl = Request.Url.GetLeftPart(UriPartial.Authority) + "/api";
var client = new JsonServiceClient(baseUrl);
var authResponse = client.Post<AuthResponse>(new Auth { UserName = "admin", Password = "12345" });
if (authResponse.ResponseStatus.ErrorCode == null)
{
//Do Something here
}
}
catch (WebServiceException ex)
{
throw ex;
}
}
Followin is Exeception Detail which i am recieving on clien.Post method:
[SerializationException: Type definitions should start with a '{', expecting serialized type 'AuthResponse', got string starting with:
Serialization exception that reads "expecting serialized type 'X', got string starting with:" means that the serializer tries to create an object from an empty string instead of a proper json-formatted string ("{Class:{Property:{Sub:value}}}").
In this case, most likely cause is server at baseUrl returning no response (interpreted as empty string) to a POST request. Misconfigured URL or exception on server side, maybe?

Servlet: proper way to redirect to index versus show view in doGet() method

Given this doGet implementation:
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (request.getParameterMap().isEmpty()) {
// DAO initialized in init() method
Collection<User> users = resource.getUsers();
if (users != null){
HttpSession session = request.getSession();
session.setAttribute("users", users);
}
request.getRequestDispatcher("/WEB-INF/users/index.jsp").forward(request, response);
}
else {
String name = request.getParameter("name");
// DAO initialized in init() method
User user = resource.getUser(name);
if (user == null){
request.setAttribute("message", "Unknown user: " + name);
request.getRequestDispatcher("/WEB-INF/errors/404.jsp").forward(request, response);
}
else {
HttpSession session = request.getSession();
session.setAttribute("user", user);
request.getRequestDispatcher("/WEB-INF/users/show.jsp").forward(request, response);
}
}
}
Questions:
Is request.getParameterMap().isEmpty() the preferred way to test for the presence of parameters?
Is there a way to infer the views' location (/WEB-INF/users/) from the either the Servlet's context or an annotation?
Is request.getParameterMap().isEmpty() the preferred way to test for the presence of parameters?
Yes, it is. But this is not the right solution for your particular case. Your code will fail if the enduser supplied an arbitrary parameter with other name than name, causing the parameter map to be not empty and thus enter the block which expects the name parameter. You should really explicitly check the request parameter name itself.
String name = request.getParameter("name");
if (name == null) {
Collection<User> users = resource.getUsers();
// ...
}
else {
User user = resource.getUser(name);
// ...
}
Is there a way to infer the views' location (/WEB-INF/users/) from the either the Servlet's context or an annotation?
Use a MVC framework (recommended) or homebrew one (not recommended, unless 100% internal/private/hobby and thus for pure learning purposes).

Programmatically log-in a user using spring security

The opposite of: How to manually log out a user with spring security?
In my app I have register new user screen, which posts to a controller which creates a new user within db (and does a few obvious checks).I then want this new user to be automatically logged in ... I kind of want somethign like this :
SecurityContextHolder.getContext().setPrincipal(MyNewUser);
Edit
Well I have almost implemented based on the answer to How to programmatically log user in with Spring Security 3.1
Authentication auth = new UsernamePasswordAuthenticationToken(MyNewUser, null);
SecurityContextHolder.getContext().setPrincipal(MyNewUser);
However, when deployed the jsp can not access my MyNewUser.getWhateverMethods() whereas it does when normal login procedure followed. the code that works nomrally, but throws an error when logged in like above is below :
<sec:authentication property="principal.firstname" />
In my controller i have this, which logs user in as normal :
Authentication auth =
new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(auth);
Where user is my custom user object(implementing UserDetails) that is newly created. The getAuthorities() method does this (just because all my users have the same role):
public Collection<GrantedAuthority> getAuthorities() {
//make everyone ROLE_USER
Collection<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
GrantedAuthority grantedAuthority = new GrantedAuthority() {
//anonymous inner type
public String getAuthority() {
return "ROLE_USER";
}
};
grantedAuthorities.add(grantedAuthority);
return grantedAuthorities;
}
You can also inject your spring security configured UserDetailsManager to your controller and use that to get the UserDetails which holds the principal and authorities to avoid duplicate code:
// inject
#Autowired
private UserDetailsManager manager;
// use in your method
UserDetails userDetails = manager.loadUserByUsername (token.getUsername ());
Authentication auth = new UsernamePasswordAuthenticationToken (userDetails.getUsername (),userDetails.getPassword (),userDetails.getAuthorities ());
SecurityContextHolder.getContext().setAuthentication(auth);
From the spring security source AbstractAuthenticationProcessingFilter:
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
Authentication authResult) throws IOException, ServletException {
if (logger.isDebugEnabled()) {
logger.debug("Authentication success. Updating SecurityContextHolder to contain: " + authResult);
}
// you need this
SecurityContextHolder.getContext().setAuthentication(authResult);
rememberMeServices.loginSuccess(request, response, authResult);
if (this.eventPublisher != null) {
eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass()));
}
successHandler.onAuthenticationSuccess(request, response, authResult);
}
Note however that the SecurityContextHolder is usually cleared upon completion of the filter chain.
For anyone trying to do this with Reactive Spring Security, this is what I did and it seemed to work.
private Mono<Authentication> authenticateUser(ServerWebExchange exchange, UserDetails userDetails,String rawPassword)
{
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(userDetails.getUsername(),rawPassword);
return reactiveAuthenticationManager.authenticate(token).filter(auth -> auth.isAuthenticated()).flatMap(auth ->
{
SecurityContextImpl securityContext = new SecurityContextImpl();
securityContext.setAuthentication(auth);
return securityContextRepository.save(exchange,securityContext).then(Mono.just(auth));
});
}

WCF Adding Custom Headers and Session

I have a web page that uses a WCF service. Multiple users maybe using the web page at any one time and therefore making requests to the WCF service which is on a remote machine.
Each user on the web page gets a unique ID, I want to add this unique ID to the request header of each request made by that user.
So far I have created the following code which correctly adds a header to the WCF message.
public class HeaderIdPusher : IClientMessageInspector
{
private static readonly string _balancerKey = "balancerId";
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
Guid userId = Guid.NewGuid();
HttpRequestMessageProperty httpRequestMessage;
object httpRequestMessageObject;
if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name, out httpRequestMessageObject))
{
httpRequestMessage = httpRequestMessageObject as HttpRequestMessageProperty;
if (string.IsNullOrEmpty(httpRequestMessage.Headers[_balancerKey]))
{
httpRequestMessage.Headers[_balancerKey] = userId.ToString();
}
}
else
{
httpRequestMessage = new HttpRequestMessageProperty();
httpRequestMessage.Headers.Add(_balancerKey, userId.ToString());
request.Properties.Add(HttpRequestMessageProperty.Name, httpRequestMessage);
}
return null;
}
public void AfterReceiveReply(ref Message reply, object correlationState)
{
}
}
However I am no stuck because I can't get the ID to persist between requests. You can see here that at the moment I am generating an ID for each request, however I can't store this in the Session of the page the user is on because the HttpContext.Current is null. Is there another way of storing this? Is there another way of passing in the HttpContext of the user on my web page?
The problem is discussed here:
http://social.msdn.microsoft.com/forums/en-US/wcf/thread/27896125-b61e-42bd-a1b0-e6da5c23e6fc
Essentially WCF doesn't have sessions, as you could pass anything you wanted as a parameter (in this case, your Unique ID) and handle it any way you wanted in your implementation.
After much hacking I found a solution, it isn't great but it works.
In the ASP.NET page before I create the WCF service instance I create an address header and endpoint:
AddressHeader header = AddressHeader.CreateAddressHeader("MyKey", "http://www.w3.org/2005/08/addressing", "MyValue");
EndpointAddress endpoint = new EndpointAddress(new Uri("http://www.myservice.com/service"), header);
Then I create an instance of the service passing in the endpoint:
using (WcfService service = new WcfService(_configName,endpoint ))
{
}
This gets the data into the WCF service, then in the HeaderIdPusher : IClientMessageInspector detailed above I pull the header value out:
public class HeaderIdPusher : IClientMessageInspector
{
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
string id = "Not found";
if(channel.RemoteAddress.Headers.Any(x=>x.Name == "MyKey"))
{
id = channel.RemoteAddress.Headers.First(x => x.Name == "MyKey").GetValue<string>();
}
This solution isn't ideal and it puts extra data into the SOAP message but it is the only way I have found of sharing data from the ASP.NET page with the WCF process.

Resources