I have a java spring mvc webapp that builds a table of statuses making ajax calls to update ping status every 3 seconds and performance/health status every 5 min. It works correctly but the only thing is I added spring security and whenever a second user logs in from a different page it resets both views instead of just building the new view. How do I make it so each new user session has their own view to update without affecting the other open browser sessions?
Here's my jsp page:
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%#page session="true" %>
<html>
<head>
<title>Site Connector</title>
<link rel="stylesheet" type="text/css" href="pages/styles/main.css">
<link rel="colorSchemeMapping" href="pages/styles/colorschememapping.xml">
<script type="text/javascript" src="pages/scripts/jquery-1.11.2.min.js"></script>
<script type="text/javascript">
function updateReachability() {
$.ajax({
url: 'updatePing',
type: 'GET',
success: function(data) {
$('#site').html(data);
}
});
}
function updateStatus() {
$.ajax({
url: 'updateStatus',
type: 'GET',
success: function(data) {
$('#site').html(data);
}
});
}
document.addEventListener('DOMContentLoaded', function() {
updateStatus();
setInterval(updateStatus, 300000);
setInterval(updateReachability, 3000);
}, false);
</script>
</head>
<body lang=EN-US link=blue vlink=purple style='tab-interval:.5in'>
<div id="site">
<div id="upper_left">
<img src="pages/sickLogo.gif" alt="SICK Inc. logo"/>
<br />
<br />
<br />
</div>
<div id="upper_right">
<c:if test="${pageContext.request.userPrincipal.name != null}">
<c:url var="logoutUrl" value="/logout"/>
<form action="${logoutUrl}" method="post" id="logoutForm">
Logged in as: ${pageContext.request.userPrincipal.name} <input type="submit" value="logout" />
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
</c:if>
</div>
<h1>Site Connector</h1>
<table>
<tr>
<th>IP Address</th>
<th>Facility Name</th>
<th>URL</th>
<th>Health Status</th>
<th>Performance Status</th>
</tr>
<c:forEach items="${site.hubs}" var="hub">
<tr>
<td bgcolor="${hub.pingStatus}">${hub.ipAddress}</td>
<td>${hub.siteName}</td>
<td>${hub.url}</td>
<td bgcolor="${hub.healthStatus}"></td>
<td bgcolor="${hub.performanceStatus}"></td>
</tr>
</c:forEach>
</table>
</div>
</body>
</html>
and here's my controller class:
#Controller
public class SiteController {
private static final Logger logger = Logger.getLogger(SiteController.class.getName());
private static String osName = System.getProperty("os.name");
private SiteManager manager = new SiteManager();
private SiteStatus site = new SiteStatus();
private ModelAndView model = new ModelAndView("SiteConnectorPage");
private boolean checkPing = true;
//method to run on initialization to build site list table from file
#RequestMapping("/connector")
public ModelAndView init() {
System.out.println("Connector method called");
//call method to create the list of error codes to search for
try
{
if(osName.matches("^.*Windows.*$"))
{
//change file location to C:/SVP/hub-connector/site-list/SiteList.csv
site = manager.buildSiteStatus("C:/p4_dominer/SiteConnector/SiteList.csv", site);
//set the ping status and URL's for each hub
if(!site.getHubs().isEmpty())
{
//set URL's for each hub and determines their reachability status
manager.buildURL(site.getHubs(), true);
}
else
{
logger.error("Site List is empty, please check contents of input file");//throw empty list exception
}
}
else //path to Linux location
{
site = manager.buildSiteStatus("/home/engineering/SVP/site-connector/site-list/SiteList.csv", site);
if(!site.getHubs().isEmpty())
{
//set URL's for each hub and determines their reachability status
manager.buildURL(site.getHubs(), false);
}
else
{
logger.error("Site List is empty, please check contents of input file");//throw empty list exception
}
}
}
catch (IOException e)
{
logger.error(e.getMessage());
}
model.addObject("site", site);
return model;
}
//method to update ping status
#RequestMapping(value = "/updatePing", method = RequestMethod.GET)
public ModelAndView updatePingStatus()
{
if(checkPing) {
try
{
if(osName.matches("^.*Windows.*$"))
{
System.out.println("updatePing method called");
//set URL's for each hub and determines their reachability status
manager.buildURL(site.getHubs(), true);
}
else
{
//set URL's for each hub and determines their reachability status
manager.buildURL(site.getHubs(), false);
}
}
catch (IOException e)
{
logger.error(e.getMessage());
}
}
return model;
}
#RequestMapping(value="/customLogin", method = RequestMethod.GET)
public ModelAndView loginPage(#RequestParam(value="error", required=false) String error,
#RequestParam(value="logout", required=false) String logout)
{
ModelAndView loginModel = new ModelAndView("customLogin");
if(error != null) {
loginModel.addObject("error", "Login was unsuccessful, Please Try Again.");
}
if(logout != null) {
loginModel.addObject("msg", "You've been logged out successfully.");
}
return loginModel;
}
#RequestMapping(value="/updateStatus", method = RequestMethod.GET)
public ModelAndView updateStatus()
{
System.out.println("updateStatus method called");
//set checkPing to false so updatePingStatus method doesn't update model concurrentlly which was causing the table to flash
checkPing = false;
if(osName.matches("^.*Windows.*$"))
{
/*test code */long startTime = System.nanoTime();
manager.getStatusData(site.getHubs(), site.getDeviceErrors(), true);
/*test code */long endTime = System.nanoTime();
/*test code */long duration = (endTime - startTime) / 1000000;
/*test code*/logger.info("updateStatus took " + duration + " ms");
}
else
{
manager.getStatusData(site.getHubs(), site.getDeviceErrors(), false);
}
checkPing = true;
return model;
}
}
Here's my web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:web="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>ERROR</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<servlet>
<servlet-name>connector</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>connector</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/connector-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
<welcome-file-list>
<welcome-file>customLogin.jsp</welcome-file>
</welcome-file-list>
</web-app>
And here's my servlet.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-4.0.xsd">
<context:component-scan base-package="com.sick.controller" />
<mvc:resources mapping="/pages/**" location="/pages/" />
<mvc:annotation-driven />
<beans:bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/pages/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<http pattern="/pages/**" security="none"/>
<http auto-config="true">
<intercept-url pattern="/login*" access="permitAll"/>
<intercept-url pattern="/customLogin*" access="permitAll"/>
<intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
<logout logout-success-url="/customLogin?logout" />
<form-login login-page="/customLogin" authentication-failure-url="/customLogin?error" default-target-url="/connector" />
<session-management><concurrency-control max-sessions="10" error-if-maximum-exceeded="true"/></session-management>
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="admin" password="admin" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
Finally came up with the answer after a lot of googling. I added sessioning to my controller class so that each client request was updating its own session object and not affecting other open browsers.
#RequestMapping("/connector")
public ModelAndView init(HttpServletRequest request) {
SiteManager manager = new SiteManager();
ModelAndView model = new ModelAndView("SiteConnectorPage");
SiteStatus siteStatus = new SiteStatus();
//create session if one doesn't exist
HttpSession session = request.getSession(true);
System.out.println("Connector method called");
try
{
if(osName.matches("^.*Windows.*$"))
{
siteStatus = manager.buildSiteStatus("C:/SICK/Site Connector/SiteList.csv");
//set the ping status and URL's for each hub
if(!siteStatus.getHubs().isEmpty())
{
//set URL's for each hub and determines their reachability status
manager.buildURL(siteStatus.getHubs(), true);
}
else
{
logger.error("Site List is empty, please check contents of input file");//throw empty list exception
}
}
else //path to Linux location
{
siteStatus = manager.buildSiteStatus("/home/engineering/SVP/site-connector/site-list/SiteList.csv");
if(!siteStatus.getHubs().isEmpty())
{
//set URL's for each hub and determines their reachability status
manager.buildURL(siteStatus.getHubs(), false);
}
else
{
logger.error("Site List is empty, please check contents of input file");//throw empty list exception
}
}
}
catch (IOException e)
{
logger.error(e.getMessage());
}
session.setAttribute("site", siteStatus);
model.addObject("site", siteStatus);
return model;
}
Related
In my Spring MVC application, I want to redirect my page from index.jsp page to final.jsp page using AJAX. But the redirected page (final.jsp) is not being displayed when I click the Redirect Page button in my application. I have used System.out.println("inside /redirect"); and System.out.println("inside /finalPage"); inside my Java code to check whether the AJAX GET request is being received at server or not, and only inside /redirect is being printed which which means that the /finalPage is not being called. Moreover, my browser's console does not show any error. So please tell, what can be the problem and where is that problem? I have posted my complete code below:
WebController.java
package com.tutorialspoint;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
#Controller
public class WebController {
#RequestMapping(value = "/index", method = RequestMethod.GET)
public String index() {
return "index";
}
#RequestMapping(value = "/redirect", method = RequestMethod.GET)
public String redirect() {
System.out.println("inside /redirect");
return "redirect:/finalPage";
}
#RequestMapping(value = "/finalPage", method = RequestMethod.GET)
public String finalPage() {
System.out.println("inside /finalPage");
return "final";
}
}
index.jsp
<%#taglib uri = "http://www.springframework.org/tags/form" prefix = "form"%>
<html>
<head>
<title>Spring Page Redirection</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<h2>Spring Page Redirection</h2>
<p>Click below button to redirect the result to new page</p>
<button onClick="redFun()">Redirect Page</button>
<script>
function redFun() {
$.ajax({
type : "GET",
url : "/HelloWeb/redirect"
});
}
</script>
</body>
</html>
final.jsp
<%#taglib uri = "http://www.springframework.org/tags/form" prefix = "form"%>
<html>
<head>
<title>Spring Page Redirection</title>
</head>
<body>
<h2>Redirected Page</h2>
</body>
</html>
web.xml:
<web-app id = "WebApp_ID" version = "2.4"
xmlns = "http://java.sun.com/xml/ns/j2ee"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Spring MVC Application</display-name>
<servlet>
<servlet-name>HelloWeb</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>HelloWeb</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
HelloWeb-servlet.xml
<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:context = "http://www.springframework.org/schema/context"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package = "com.tutorialspoint" />
<bean class = "org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name = "prefix" value = "/WEB-INF/jsp/" />
<property name = "suffix" value = ".jsp" />
</bean>
</beans>
Your browser is not following the redirect because you're using ajax to hit your controller's redirect method. You have two options:
Don't use ajax at all, and let your browser respond naturally to the redirect status.
function redFun() {
window.location = "/HelloWeb/redirect";
}
Look for an HTTP 302 response to the XmlHttpRequest, and change window.location to the value of the Location header in the response:
function redFun() {
$.ajax({
type: "GET",
url: "/HelloWeb/redirect"
}).fail(function (jqXHR, status, err) {
if (jqXHR.status === 302) {
window.location = jqXHR.getResponseHeader('Location');
}
});
}
Hi I am facing two problem
HTTP status 404 (!important)
When I select Run on server on one particular project 'Two different dynamic projects executes' .
HTTP Status 404
message /RealTimeCurValue/RTCurrValue.do
description The requested resource is not available.
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<display-name>Pavan</display-name>
<welcome-file-list>
<welcome-file>RTCurrValue.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>RTCV</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>ContextConfigLocation</param-name>
<param-value>/WEB-INF/classes/Spring/RTCV-servlet.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>RTCV</servlet-name>
<url-pattern>*.to</url-pattern>
</servlet-mapping>
RTCV-servlet.xml
<context:component-scan base-package="com.fact.mvcApp" />
<bean id="RTC"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/" />
<property name="suffix" value=".jsp" />
</bean>
RealTimeCurrValueController.java
#Component
#RequestMapping("/")
public class RealTimeCurrValueController
{
#Autowired
private RealTimeCurrValueService service;
public RealTimeCurrValueController()
{
System.out.println(this.getClass().getSimpleName()+ "Created");
}
#RequestMapping(value="/RTCurrValue.do", method = RequestMethod.POST)
public ModelAndView realTimeCurrValueController( #ModelAttribute RealTimeCurrValueDTO dto , HttpServletRequest req)
{
System.out.println("RealTimeCurrValue Controller Started ");
CbBtc rtvcDTO = null;
System.out.println(dto);
if(dto!= null)
{
String cValue = dto.getCryptoCurrency();
System.out.println("cValue-----" +cValue);
try
{
rtvcDTO = service.rtcvService(cValue);
}
catch (IOException e)
{
e.printStackTrace();
}
if(rtvcDTO != null)
{
HttpSession session =req.getSession();
System.out.println(" Success");
return new ModelAndView("Welcome.jsp" , "value" , rtvcDTO.getAmount() );
}
}
System.out.println("RealTimeCurrValue Controller Ended ");
return null;
}
}
RTCurrValue.jsp
<form action="RTCurrValue.do" method="post">
Currency: <input type="text" name="currency" />
<input type= "submit" value="OK">
</form>
Your form action is relative to the current page i.e. /RTCurrValue, so the url used to post the form is "/RTCurrValue/RTCurrValue.do" which is giving the 404.
If your web app is running as the ROOT web app then try adding a / to the form action. action="/RTCurrValue.do".
If your web app is running in some other context then add the context to the action. action="/someContext/RTCurrValue.do"
Or better construct the URL using the standard tags.
<c:url var="formAction" value="/RTCurrValue.do"/>
<form action="${formAction}" method="post">
An app built from the spring petclinic sample app has added spring security with a custom login form.
The app does not have a WebMvcConfiguration.java class as suggested by this tutorial. Instead, it has the following line in mvc-core-config.xml:
<mvc:view-controller path="/login" view-name="login" />
I have done Ctrl-H in eclipse and done a key word search for the term /login in the entire workspace, but no controller is visible. I also looked in the messages-jc sample project referred to in the tutorial link above, but could not find a "/login" controller there either.
How can I add a controller that will perform spring authentication with the standard username and password, but that will also allow me to subsequently add additional code to the authentication process when the login form at the "/login" url is submitted?
Is it as simple as adding the following to SomeOtherController.java :
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String showLoginForm(Model model) {
//what goes here?
return "public/loginform";
}
#RequestMapping(value = "/login", method = RequestMethod.POST)
public String processLoginForm(HttpSession session, #ModelAttribute("user") User user,
BindingResult result, Model model, final RedirectAttributes redirectAttributes)
{
//what goes here?
return "secure/main";
}
In spring-security-core jar, there is an interface UserDetailsService which has a method
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
You can implement this interface and create your code your own logic, like
#Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
#Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username) {
User user = userService.findUserByUsername(username);
if (user != null) {
String password = user.getPassword();
boolean enabled = user.getActive();
boolean accountNonExpired = user.getActive();
boolean credentialsNonExpired = user.getActive();
boolean accountNonLocked = user.getActive();
Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for (Role r : user.getRoles()) {
authorities.add(new SimpleGrantedAuthority(r.getAuthority()));
}
org.springframework.security.core.userdetails.User securedUser = new org.springframework.security.core.userdetails.User(
username, password, enabled, accountNonExpired,
credentialsNonExpired, accountNonLocked, authorities);
return securedUser;
} else {
throw new UsernameNotFoundException(
"Unable to find user with username provided!!");
}
}
and then create an object of DaoAuthenticationProvider using
<bean id="daoAuthenticationProvider"
class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="userDetailsService"></property>
</bean>
Finally, supply this DaoAuthenticationProvider to ProviderManager
<bean class="org.springframework.security.authentication.ProviderManager">
<constructor-arg>
<list>
<ref bean="daoAuthenticationProvider" />
</list>
</constructor-arg>
</bean>
<security:authentication-manager>
<security:authentication-provider
user-service-ref="userDetailsService">
<security:password-encoder hash="plaintext"></security:password-encoder>
</security:authentication-provider>
</security:authentication-manager>
adding web.xml details
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-config/spring-*.xml</param-value>
</context-param>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
For this purpose you can use your own CustomAuthenticationProvider by implementing AuthenticationProvider from org.springframework.security.authentication and override public Authentication authenticate(Authentication authentication) method.
code example is given below
public class CustomAuthenticationProvider implements AuthenticationProvider {
#Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
String username = authentication.getName();
String password = (String) authentication.getCredentials();
List<GrantedAuthority> grantedAuths = new ArrayList<>();
//validate and do your additionl logic and set the role type after your validation. in this code i am simply adding admin role type
grantedAuths.add(new SimpleGrantedAuthority("ROLE_ADMIN" ));
return new UsernamePasswordAuthenticationToken(username, password, grantedAuths);
}
#Override
public boolean supports(Class<?> arg0) {
return true;
}
}
so default login handler i.e. /login(POST) will be handled by this.
Your jsp file involving login form should be like this.
<%# page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<title>Spring security</title>
<style>
.errorblock {
color: #ff0000;
background-color: #ffEEEE;
border: 3px solid #ff0000;
padding: 8px;
margin: 16px;
}
</style>
</head>
<body onload='document.f.j_username.focus();'>
<h3>Login with Username and Password</h3>
<c:if test="${not empty error}">
<div class="errorblock">
Your login attempt was not successful, try again.
Caused :
${sessionScope["SPRING_SECURITY_LAST_EXCEPTION"].message}
</div>
</c:if>
<%-- <c:url value="/j_spring_security_check" var="index.htm" />
<form name='f' action="${index.htm}" method='POST'> --%>
<form name='f' action="<c:url value='j_spring_security_check' />" method='POST'>
<table>
<tr>
<td>User:</td>
<td><input type='text' name='j_username' value=''>
</td>
</tr>
<tr>
<td>Password:</td>
<td><input type='password' name='j_password' />
</td>
</tr>
<tr>
<td colspan='2'><input name="submit" type="submit"
value="submit" />
</td>
</tr>
<tr>
<td colspan='2'><input name="reset" type="reset" />
</td>
</tr>
</table>
</form>
</body>
</html>
Your spring-security.xml file should look like this.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<security:http auto-config="true" >
<security:intercept-url pattern="/index*" access="ROLE_USER" />
<security:form-login login-page="/login.htm" default-target-url="/index.htm"
authentication-failure-url="/loginerror.htm" />
<security:logout logout-success-url="/logout.htm" />
<!-- <security:csrf disabled="true"/> -->
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<!-- <security:user-service>
<security:user name="syed" password="1111" authorities="ROLE_USER" />
</security:user-service> -->
<security:jdbc-user-service data-source-ref="dataSource"
users-by-username-query="select username, password, active from users where username=?"
authorities-by-username-query="select us.username, ur.authority from users us, user_roles ur
where us.user_id = ur.user_id and us.username =? "
/>
</security:authentication-provider>
</security:authentication-manager>
</beans>
Inside the configuration element, you can restrict access to particular URLs with one or more elements. Each element specifies a URL pattern and a set of access attributes required to access the URLs. Remember that you must always include a wildcard at the end of a URL pattern. Failing to do so will make the URL pattern unable to match a URL that has request parameters.
<security:http auto-config="true" >
<security:intercept-url pattern="/index*" access="ROLE_USER" />
<security:intercept-url pattern="/Transit*" access="ROLE_USER" />
<security:form-login login-page="/login.htm" default-target-url="/index.htm"
authentication-failure-url="/loginerror.htm" />
<security:logout logout-success-url="/logout.htm" />
</security:http>
When ever we are going to describe a url without any security, Then we should remove the particular url from the above lines of code under security configured xml file. for example if we dont need any security for index page then the above coding should look like this.
<security:http auto-config="true" >
<security:intercept-url pattern="/Transit*" access="ROLE_USER" />
<security:form-login login-page="/login.htm" default-target-url="/index.htm"
authentication-failure-url="/loginerror.htm" />
<security:logout logout-success-url="/logout.htm" />
</security:http>
I'm developing a Java application and I'm using Spring MVC. I'm a newbie and I'm trying to load some static content like css files and images in my home page. When I try to load some of these files I get a 405 error (GET method not allowed).
My project structure (for the web part) is
-WebContent
--MetaInf
--resources
--views
--WEB_INF
---web.xml
---springapp-dispatcher.xml
here's my web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
metadata-complete="true">
<servlet>
<servlet-name>springapp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springapp</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
my springapp-dispatcher.xml (without the initial part)
<mvc:annotation-driven/>
<mvc:resources mapping="/resources/**"
location="/resources/" />
<context:component-scan base-package="polibeacon.web"></context:component-scan>
<bean class= "org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
I only have a controller, named HomeController.java
#Controller
public class HomeController {
#RequestMapping( value = "/", method = RequestMethod.GET )
public String index(Model model) {
model.addAttribute(new User());
return "index";
}
#RequestMapping(value="/registration", method = RequestMethod.GET)
public String registration(Model model) {
model.addAttribute(new User());
return "registration";
}
#RequestMapping(method=RequestMethod.POST)
public String registerUser(#Valid User user, BindingResult bindingResult) {
if(bindingResult.hasErrors()) {
return "registration";
}
// save user
return "index";
}
}
and here's the index.jsp page
<!-- CSS -->
<link href="<c:url value="/resources/bootstrap/css/bootstrap.min.css" />" rel = "stylesheet">
<link href="<c:url value="/resources/css/style.css" />" rel = "stylesheet">
<!-- Scripts -->
</head>
<body>
<div class = "container">
<div class = "row">
<div class = "col-md-3"></div>
<div class = "col-md-6">
<div class = "jumbotron" style = "text-align: center;">
<img src = "images/logo.png" style = "display: block; margin-left: auto; margin-right: auto;">
<h2>Header</h2>
<form:form method="post" modelAttribute="user">
<form:input path="username" placeholder="Username"/>
<form:password path="password" placeholder="Password"/>
</form:form>
</div>
</div>
</div>
Sign Up
</div>
</body>
</html>
what's wrong?
I am experiencing some issues with the application. I have a registration form which is post to another page from the controller
this page displays the results of the query from the registration form. On the results page i select a record and it returns me with the
data to the registration page. The user should be able to update the record once its returned or execute a query again.
The problems i am having is when the user is on the registration form and executes a query they are posted to the results page
the results page is displayed however the url does not change. The registration url is http://localhost:8084/crimeTrack/citizen_registration.htm
when posted to the results page by clicking the query button the url is still http://localhost:8084/crimeTrack/citizen_registration.htm
when a record is clicked/selected on the results page (which has several records) the user is posted back to the registration page with the
selected record and it is displayed for the user to now execute an update or a query again, the url is http://localhost:8084/crimeTrack/getCitizen/1985121244.htm
and the user is now on the registration page.
If i click query/update again i am getting an HTTP 400 error and the url is reading http://localhost:8084/crimeTrack/getCitizen/citizen_registration.htm/
and this is not a valid URL mapping in the Controller. I think the url should be http://localhost:8084/crimeTrack/citizen_registration.htm when the registration page is
requested. I am not sure when the POST from the results page takes the user back to the registration page is the url should be http://localhost:8084/crimeTrack/getCitizen/1985121244.htm
the attached number is the citizen number. Under is my code i am not sure if i am doing these calls correctly and i would like an explanation for the results i am getting as well as
a solution to the issues experienced;
Pages are submitted using jquery:
This is an example for the registration page and all other pages follow the same pattern
JScript
function submitPage(){
document.getElementById("citizenRegistration").action="citizen_registration.htm";
//document.getElementById("citizenRegistration").target="_self";
document.getElementById("citizenRegistration").method = "POST";
document.getElementById("citizenRegistration").submit();
}
citizen_registration.jsp
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN">
<html lang="en">
<head>
<title>Citizen Registration</title>
</head>
<body>
<div id="tab1" class="divGroup">
<form:form id="citizenRegistration" name ="citizenRegistration" commandName="citizens">
........................
<div class="buttons">
<ol>
<li><input class="button" id="save" type="submit" name= "user_request" value="Save"/>
<input class="button" id="update" type="submit" name= "user_request" value="Update"/>
<input class="button" id="query" type="submit" name= "user_request" value="Query"/>
</li>
</form:form>
</div>
</body>
</html>
citizenList.jsp
<!DOCTYPE html>
<html lang="en">
<head>
<script type="text/javascript">
function submitPage(socialSecurityNumber){
document.getElementById("citizenList").action="getCitizen/1985121244.htm";//harded coded for testing
//document.getElementById("citizenList").target="_self";
document.getElementById("citizenList").method = "POST";
document.getElementById("citizenList").submit();
}
function GetCitizenTypeDescription(citizenTypeId){
$.ajax({
type:'GET',
url:'getCitizenTypeDescription.htm',
data:{citizenTypeId:citizenTypeId},
dataType: 'text',
success: function (data) {
$('.citizenTypeId').each(function(i){
if($(this).val() === citizenTypeId){
//finds parent div
var parent = $(this).parent();
//search for child element wit class name citizenTypeDesc
var thisCitizenTypeDesc = parent.children('.citizenTypeDesc');
thisCitizenTypeDesc.text(data);
}
});
}
});
}
<title>Citizen Search Results</title>
</head>
<body>
<form:form id="citizenList" name ="citizenList">
<div id ="content">
<c:forEach items="${citizens}" var="citizen">
<div id="table">
<div>
<p><canvas class="canvas" height="240" width="320"></canvas>
</div>
<label class="citizenTypeDesc"></label></br>
<a class="socialSecurityNumber" href="${citizen.socialSecurityNumber}">${citizen.fName} ${citizen.lName}</a>
<input type="hidden" id="photo" value="${citizen.photo}" class="photos"/>
<input type="hidden" id="socialSecurityNumber" value="${citizen.socialSecurityNumber}" />
<input type="hidden" class="citizenTypeId" value="${citizen.citizenTypeId}"/>
</div>
</c:forEach>
</div>
</form:form>
</body>
</html>
CitizenRegistrationController.java
#Controller
public class CitizenRegistrationController {
private final Logger logger = Logger.getLogger(getClass());
#Autowired
private CitizenTypeManager citizenTypeManager;
............
Map<String, Object> myCitizenType = new HashMap<String, Object>();
.......
#InitBinder("citizens")
protected void initBinder(WebDataBinder binder){
//removes white spaces
binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
//formats date
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
//By passing true this will convert empty strings to null
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
dateFormat.setLenient(false);
//binder.setValidator(new OfficerRegistrationValidation());
binder.setValidator(citizenRegistrationValidation);
binder.registerCustomEditor(Integer.class,new CustomIntEditor());
}
#RequestMapping(value="citizen_registration.htm", method = RequestMethod.GET)
public ModelAndView loadPage(#ModelAttribute Citizens citizen,
BindingResult result,
ModelMap m,
Model model,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
try{
logger.debug("In Http method for CitizenRegistrationController");
myCitizenType.put("citizenTypeList", this.citizenTypeManager.getCitizenType());
myGender.put("genderList", this.genderManager.getGenderList());
......
return new ModelAndView("citizen_registration");
}catch(Exception e){
logger.error("Exception in CitizenRegistrationController - ModelAndView loadPage "+e);
request.setAttribute("error",e.getMessage());
return new ModelAndView("error_page");
}
}
#RequestMapping(value="citizen_registration.htm", method = RequestMethod.POST)
public ModelAndView handleRequest(#Valid #ModelAttribute Citizens citizen,
BindingResult result,
ModelMap m,
Model model,
#RequestParam(value="user_request") String user_request) throws Exception {
try{
logger.debug("In Http method for CitizenRegistrationController - Punishment Registration");
logger.debug("User Request Is " + user_request);
if(result.hasErrors()){
logger.debug("Has Errors");
return new ModelAndView("citizen_registration");
}else{
//check if its a save of an update
if(user_request.equals("Save")){
citizenManager.RegisterCitizen(citizen);
model.addAttribute("icon","ui-icon ui-icon-circle-check");
model.addAttribute("results","Record Was Saved");
return new ModelAndView("citizen_registration");
}else if (user_request.equals("Query")){
logger.debug("about to preform query");
//citizenManager.getListOfCitizens(citizen);
if(citizenManager.getListOfCitizens(citizen).isEmpty()){
model.addAttribute("icon","ui-icon ui-icon-circle-close");
model.addAttribute("results","Notice: Query Caused No Records To Be Retrived!");
}else{
model.addAttribute("citizens",citizenManager.getListOfCitizens(citizen));
return new ModelAndView("citizenList");
}
}else if (user_request.equals("Update")){
logger.info("About to do update");
citizenManager.UpdateCitizen(citizen);
return new ModelAndView("citizen_registration");
}
}
logger.debug("Has No Errors");
return new ModelAndView("citizen_registration");
}catch(Exception e){
logger.error("Exception in CitizenRegistrationController - ModelAndView loadPage "+e);
//request.setAttribute("error",e.getMessage());
return new ModelAndView("citizen_registration");
}
}
#RequestMapping(value="getCitizen/{socialSecurityNumber}.htm", method = RequestMethod.POST)
public ModelAndView getCitizen(#PathVariable Integer socialSecurityNumber,#ModelAttribute Citizens citizen,
BindingResult result,ModelMap m,Model model,HttpServletRequest request,
HttpServletResponse response) {
try {
model.addAttribute("citizens",citizenManager.getCitizen(socialSecurityNumber));
//model.addAttribute("citizens",citizenManager.getCitizen(socialSecurityNumber));
} catch (Exception e) {
logger.error("Exception in CitizenRegistrationController - ModelAndView getCitizen "+e);
}
return new ModelAndView("citizen_registration");
}
#RequestMapping(value="getCitizenTypeDescription.htm", method=RequestMethod.GET)
public #ResponseBody String citizenTypeDescription(#RequestParam Integer citizenTypeId)throws Exception{
String data = "No Data Found";
try{
data = citizenTypeManager.getCitizenTypeDescription(citizenTypeId);
}catch(Exception e){
data = e.getMessage();
logger.error("Exception In getCitizenTypeDescription.htm error : " + e);
}
return data;
}
//setter methods
/**
* #param citizenTypeManager the citizenTypeManager to set
*/
public void setCitizenTypeManager(CitizenTypeManager citizenTypeManager) {
this.citizenTypeManager = citizenTypeManager;
}
................................
}
Edit
I tried using return new ModelAndView("redirect:/citizenList.htm"); in the controller when the user clicks query however i am getting 404 Not Found - http://localhost:8084/crimeTrack/citizenList.htm"
Servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/beans/spring-context-3.0.xsd">
<!-- __________________________________________________________________________________________________ -->
<!-- Supports annotations and allows the use of #Controller, #Required, #RequestMapping -->
<context:annotation-config/>
<context:component-scan base-package="com.crimetrack.business"/>
<context:component-scan base-package="com.crimetrack.jdbc"/>
<context:component-scan base-package="com.crimetrack.service"/>
<context:component-scan base-package="com.crimetrack.web" />
<mvc:annotation-driven />
<mvc:resources mapping="/resources/**" location="/public-resources/"/>
<!-- __________________________________________________________________________________________________ -->
<!-- Forwards requests to the "/" resource to the "login" view -->
<mvc:view-controller path="/login" view-name="login"/>
<!-- Forwards requests to the "/" resource to the "officer_registration" view -->
<mvc:view-controller path="/officer_registration" view-name="officer_registration"/>
<!-- Forwards requests to the "/" resource to the "citizenList" view -->
<mvc:view-controller path="/citizenList" view-name="citizenList"/>
<!-- Forwards requests to the "/" resource to the "citizen_registration" view -->
<mvc:view-controller path="/citizen_registration" view-name="citizen_registration"/>
<!-- __________________________________________________________________________________________________ -->
<!-- <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/> -->
<!-- Is used to process method level annotations -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
<!-- __________________________________________________________________________________________________ -->
<!-- <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/> -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="messages"/>
</bean>
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
<!-- __________________________________________________________________________________________________ -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
The problem is you are using relative paths here when you say action="citizen_registration.htm".
Change it to
document.getElementById("citizenRegistration").action="/crimeTrack/citizen_registration.htm";
or
document.getElementById("citizenRegistration").action="../citizen_registration.htm";
1) change the input type to button instead of submit and add an onclick event that will call your submitPage function passing in the action to call
<input class="button" id="save" type="button" name="user_request" value="Save" onclick="submitPage('citizen_registration.htm');"/>
<input class="button" id="update" type="button" name="user_request" value="Update" onclick="submitPage('citizen_registration.htm');"/>
<input class="button" id="query" type="button" name="user_request" value="Query" onclick="submitPage('citizen_list.htm');"/>
2) change your submitPage function to set the action based on which button was clicked
function submitPage(action){
document.getElementById("citizenRegistration").action = action;
document.getElementById("citizenRegistration").method = "POST";
document.getElementById("citizenRegistration").submit();
}
3) have 2 controller methods, one mapped to save/update, the other mapped to list
#RequestMapping(value="citizen_list.htm", method = RequestMethod.POST)
public ModelAndView getCitizenList(#Valid #ModelAttribute Citizens citizen, BindingResult result, ModelMap m, Model model, #RequestParam(value="user_request") String user_request) throws Exception {
try{
logger.debug("about to preform query");
//citizenManager.getListOfCitizens(citizen);
if(citizenManager.getListOfCitizens(citizen).isEmpty()){
model.addAttribute("icon","ui-icon ui-icon-circle-close");
model.addAttribute("results","Notice: Query Caused No Records To Be Retrived!");
}else{
model.addAttribute("citizens",citizenManager.getListOfCitizens(citizen));
return new ModelAndView("citizenList");
}
}catch(Exception e){
logger.error("Exception in CitizenRegistrationController - ModelAndView loadPage "+e);
//request.setAttribute("error",e.getMessage());
return new ModelAndView("citizen_registration");
}
}
#RequestMapping(value="citizen_registration.htm", method = RequestMethod.POST)
public ModelAndView handleRequest(#Valid #ModelAttribute Citizens citizen, BindingResult result, ModelMap m, Model model, #RequestParam(value="user_request") String user_request) throws Exception {
try{
logger.debug("In Http method for CitizenRegistrationController - Punishment Registration");
logger.debug("User Request Is " + user_request);
if(result.hasErrors()){
logger.debug("Has Errors");
return new ModelAndView("citizen_registration");
}else{
//check if its a save of an update
if(user_request.equals("Save")){
citizenManager.RegisterCitizen(citizen);
model.addAttribute("icon","ui-icon ui-icon-circle-check");
model.addAttribute("results","Record Was Saved");
return new ModelAndView("citizen_registration");
} else if (user_request.equals("Update")){
logger.info("About to do update");
citizenManager.UpdateCitizen(citizen);
return new ModelAndView("citizen_registration");
}
}
logger.debug("Has No Errors");
return new ModelAndView("citizen_registration");
}catch(Exception e){
logger.error("Exception in CitizenRegistrationController - ModelAndView loadPage "+e);
//request.setAttribute("error",e.getMessage());
return new ModelAndView("citizen_registration");
}
}