404 Page not found after login in custom login page - spring

I am new in Spring and I'm trying to implement a custom login page. I am able to redirect to the custom login page but it goes to error 404 when I hit the Submit button in my page. The url went to : http://localhost:12345/login?username=abcd&password=qwer
Here is my code of the htm, controller and also the security config:
SecurityConfig.java
http
.authorizeRequests()
.antMatchers("/main",
"/main#/home",
"/login**",
"/resources/**",
"/css/**",
"/images/**",
"/js/**",
"/std/**",
"/system/**",
"/favicon.ico",
"/rest/**",
"/rest/user/**" ).permitAll()
.anyRequest().authenticated()
.and().csrf().disable()
.formLogin()
.loginPage("/main#/login").permitAll()
.defaultSuccessUrl("/main#/home")
.failureUrl("/main#/page/b").permitAll();
LoginController.Java
#RestController
#RequestMapping(value = "/rest/user")
public class LoginController
{
#RequestMapping(value = "login")
public String login(Model model, String error, String logout) {
if (error != null)
model.addAttribute("errorMsg", "Your username and password are invalid.");
if (logout != null)
model.addAttribute("msg", "You have been logged out successfully.");
return "login";
}
}
login-content.htm
<div class="col-md-6 col-md-offset-3">
<h2>Login</h2>
<form name="form" action="/login" ng-controller="LoginController" role="form">
<div class="form-group" ng-class="{ 'has-error': form.username.$dirty && form.username.$error.required }">
<label for="username">Username</label>
<input type="text" name="username" id="username" class="form-control" ng-model="user.username" required />
<span ng-show="form.username.$dirty && form.username.$error.required" class="help-block">Username is required</span>
</div>
<div class="form-group" ng-class="{ 'has-error': form.password.$dirty && form.password.$error.required }">
<label for="password">Password</label>
<input type="password" name="password" id="password" class="form-control" ng-model="user.password" required />
<span ng-show="form.password.$dirty && form.password.$error.required" class="help-block">password is required</span>
</div>
<input type="submit" ng-click="login(user)" value="Submit">
</form>
Thanks!

At the end I have modified the "action" in the Login-content.htm to another word (e.g. perform_login) and also added .loginProcessingUrl("/perform_login").permitAll() in the SecurityConfig.java.
Besides, the another problem is Spring Security will need to have a specific POST method in order to authenticate it. I have added method="POST" in the HTM page.
Thanks!

Related

Failed to load resource 405

I'm a bit at a loss here.
I have a thymeleaf page and a spring-boot backend that takes in a user object, getting the object to the page is fine, my problem comes in when I'm trying to get it to the back end to do stuff with it.
I keep getting the following
2021-09-15 09:21:07.834 WARN 3624 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported]
and on the browser
Failed to load resource: the server responded with a status of 405 ()
for my controller I have the following
#Controller("/user")
public class UserController {
#Autowired
private UserService userService;
#Autowired
private ModelMapper modelMapper;
#RequestMapping(value = "/add")
public String addUser(#ModelAttribute("user") final UserDto userDto) {
//do stuff
//userService.save(modelMapper.map(userDto, User.class));
return "/user";
}
}
as for my thymeleaf page
<form th:action="#{/user/add}" th:object="${user}" method="post">
<label for="fullName">Full Name</label>
<input id="fullName" class="form-control form-group" type="text" th:field="*{fullName}">
<label for="email">Email</label>
<input id="email" class="form-control form-group" type="email" th:field="*{email}">
<label for="password">Password</label>
<input id="password" class="form-control form-group" type="password" th:field="*{password}">
<p>
<button class="form-group form-control btn btn-primary" type="submit" value="Submit">Submit</button>
</p>
</form>
What am I missing here?
I did try to mess around the #GetMapping, #PostMapping, #RequestMapping(method = GET), #RequestMapping(method = POST), #RequestMapping(method = {GET, POST})
I also tried <form ... th:method="post"> and <form ... th:method="get">
But none of these seems to work.
You add global /user in #Controller. this annotation is used to implement Web Application not for path and it is better to give global path in application.properties like below code. Inside addUser() method you want to return with page name like return "user" if go to the url then put return "redirect:/user"
Here down is modified code:
application.properties
server.servlet.contextPath=/user/
Controller
#Controller
public class UserController {
#Autowired
private UserService userService;
#Autowired
private ModelMapper modelMapper;
#RequestMapping(value = "/add", method = RequestMethod.POST)
public String addUser(#ModelAttribute("user") final UserDto userDto) {
//do stuff
//userService.save(modelMapper.map(userDto, User.class));
return "pagename"; // enter page name where you wanna go not url
}
}
Template
<form th:action="#{/add}" th:object="${user}" method="post">
<label for="fullName">Full Name</label>
<input id="fullName" class="form-control form-group" type="text" th:field="*{fullName}">
<label for="email">Email</label>
<input id="email" class="form-control form-group" type="email" th:field="*{email}">
<label for="password">Password</label>
<input id="password" class="form-control form-group" type="password" th:field="*{password}">
<p>
<button class="form-group form-control btn btn-primary" type="submit" value="Submit">Submit</button>
</p>
</form>

How can I fix the CSRF related issues when it is enabled using Spring Boot with Spring Security?

I have a spring boot application. I am using Spring Security. I am facing two issues when CSRF is enabled. Please find the below issues, code and screenshots. How can I fix this?
Whenever the server is restarted, the login always fails the first time. It gives 404 error. But it is successful the second time.
I am using customAuthenticationFailureHandler in case if login is
failed, I am setting the error message in session and redirecting it
to login jsp to display it. It was working fine before CSRF was
enabled. Now, it looks like the value stored in session is destroyed
Security configuration
#Override
protected void configure(HttpSecurity http) throws Exception {
//http.csrf().disable();
http
.authorizeRequests()
.antMatchers("/ui/static/assets/**").permitAll()
.antMatchers("/register", "/forgotPassword").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/LoginPage")
.loginProcessingUrl("/authenticate")
.permitAll()
.defaultSuccessUrl("/addDocument")
.failureHandler(customAuthenticationFailureHandler)
.and().exceptionHandling().accessDeniedPage("/Access_Denied")
.and().logout().permitAll().invalidateHttpSession(true);
}
CustomAuthenticationFailureHandler
#Component
public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {
#Override
public void onAuthenticationFailure(
HttpServletRequest request,
HttpServletResponse response,
AuthenticationException exception)
throws IOException, ServletException {
String errMsg=exception.getMessage();;
request.getSession().setAttribute("loginErrorMessage", errMsg);
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.sendRedirect(request.getContextPath()+"/login?error");
}
}
Login.jsp
<c:set var="params" value="${requestScope['javax.servlet.forward.query_string']}"/>
<div class="account-content">
<c:if test="${params eq 'error' && loginErrorMessage ne null}">
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<strong>${loginErrorMessage}</strong>
</div>
</c:if>
<form action="${pageContext.servletContext.contextPath}/authenticate" class="form-horizontal" method="post" id="formLogin" data-parsley-validate="">
<sec:csrfInput />
<div class="form-group m-b-25">
<div class="col-12">
<label for="emailaddress">Email address<span class="text-danger">*</span></label>
<input class="form-control input-lg" type="email" name="username" id="username" placeholder="Enter your email" data-parsley-required="true">
</div>
</div>
<div class="form-group m-b-25">
<div class="col-12">
Forgot your password?
<label for="password">Password<span class="text-danger">*</span></label>
<input class="form-control input-lg" type="password" id="pwd" name="password" placeholder="Enter your password" data-parsley-required="true">
</div>
</div>
<div class="form-group account-btn text-center m-t-10">
<div class="col-12">
<button class="btn w-lg btn-rounded btn-lg btn-primary waves-effect waves-light"
id="signInBtn" type="submit" value="Next" >Sign In
<i class="fas fa-spinner fa-spin" id="loadingBtn" style="display:none;"></i></button>
</div>
</div>
</form>
<div class="clearfix"></div>
</div>

Spring Security with Angular2

I'm trying to authenticate my user from an Angular2 form using Spring Security, but its not working. I've looked all over the web, but seem to find no right answer to it, could someone point out where I am going wrong -
Here's a snippet from my spring-security.xml -
<security:form-login login-page="/"
authentication-failure-url="/security/login"
default-target-url="/"/>
<security:access-denied-handler error-page="/security/denied"/>
<security:logout invalidate-session="true"
logout-success-url="/security/logout/success"
logout-url="/security/logout"/>
Here's my angular2 form -
<form (ngSubmit)="onLogin(f.value)" class="form-horizontal" role="form" #f="ngForm">
<div class="form-group">
<label class="col-sm-3 control-label" for="j_username">Username:</label>
<div class="col-sm-8">
<input type="text" class="form-control" placeholder="Username" name="j_username" [(ngModel)]="user.userName"
maxlength="50" id="j_username" required >
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label" for="j_password">Password:</label>
<div class="col-sm-8">
<input type="password" class="form-control" placeholder="Password" name="j_password" [(ngModel)]="user.password"
maxlength="50" id="j_password" required>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-8 col-sm-10">
<input type="submit" class="btn btn-default" value="Login">
</div>
</div>
</form>
And here's the component code -
onLogin(f) {
this.userService.makeHttpCall(f);
}
And finally the service which calls the spring security -
makeHttpCall(f): void {
let userName = f['j_username'];
let password = f['j_password'];
let data = 'j_username='+userName+'&j_password='+password;
console.log(data);
let headers = new Headers({'Content-Type': 'application/x-www-form-urlencoded'});
let options = new RequestOptions({headers: headers}
);
this.http.post('/j_spring_security_check', data, options)
.map(this.extractData)
.catch(this.handleError);
}
Could someone point out where i am going wrong? the http call, does not make it to the AuthenticationManager defined in my spring security configuration.
In Angular2, HTTP calls are triggered as soon as you subscribe to them. Adjust the code like this:
this.http.post('/j_spring_security_check', data, options)
.map(this.extractData)
.catch(this.handleError).
.subscribe(data => {
// do something here with the response
})

spring RequestMapping not working without ModelAttribute

I have controller class with following request mapping method.
appStart() method is responsible for redirecting user to login.html and
logout() is responsible for invalidating session and redirecting user
back to login.jsp
if I remove #ModelAttribute from their parameter then these two methods are throwing exception, is there any hack to get these methods working without modelattribute?
controller methods.
#RequestMapping(value="/",method=RequestMethod.GET)
public String appStart(#ModelAttribute("tempAdmin") Admin tempAdmin) {
return "login.jsp";
}
#RequestMapping(method = RequestMethod.POST,name="doLogin")
public ModelAndView doLogin(#ModelAttribute("tempAdmin") Admin tempAdmin, HttpServletRequest request) {
ModelAndView mvc = new ModelAndView();
/*
Buisness logic
*/
mvc.setViewName("home.jsp");
return mvc;
}
#RequestMapping("doLogout")
public String logout(HttpServletRequest request) {
HttpSession session = request.getSession(false);
if(session != null){
session.invalidate();
}
return "login.jsp";
}
login.jsp
<form:form action="doLogin" modelAttribute="tempAdmin" cssClass="form-horizontal">
<div class="form-group">
<label for="username" class="col-sm-2 control-label">Username</label>
<div class="col-sm-10">
<form:input cssClass="form-control" path="adminId" placeholder="username" />
</div>
</div>
<div class="form-group">
<label for="passwd" class="col-sm-2 control-label">Password</label>
<div class="col-sm-10">
<form:password path="password" cssClass="form-control" id="passwd" placeholder="password" />
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">Sign in</button>
</div>
</div>
</form:form>
stacktrace.
Caused by: java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'tempAdmin' available as request attribute
at org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:144)
at org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getBindStatus(AbstractDataBoundFormElementTag.java:168)
at org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getPropertyPath(AbstractDataBoundFormElementTag.java:188)
I will tell you how to change your controller, to avoid binding result problem. Try this :
#RequestMapping(method = RequestMethod.POST,name="doLogin")
public String doLogin(#ModelAttribute("tempAdmin") Admin tempAdmin, HttpServletRequest request,Model model) {
model.addAttribute("tempadmin",new Admin());
// business logic
return "home";
}
Try this out, and if you have any other classes, then add the model.addAttribute for that as well. Can you post your JSP too?

Issue with the Multiaction Controller in Spring

I am having a jsp page from which i have to pass the control to the next page.
And i am using Multiaction Controller for that but its giving me an error 404.
My JSP File is
<form id="form1" name="form1" method="post" action="registerSuccessControl.htm" commandName="register" >
<strong> <label> <label> <label>
<div align="center">Registeration</div>
</label></strong> <label></label>
<h1> </h1>
<p>
First Name <input type="text" name="textfield" accesskey="1"
tabindex="1" /> <label>
Last Name</label> <strong> <input type="text"
name="textfield3" />
</strong>
</p>
and this is my Controller
#RequestMapping("/registerSuccessControl.htm")
public ModelAndView registerSuccessControl(#ModelAttribute("register") Register register,BindingResult brResult,HttpServletRequest request,HttpServletResponse response) throws Exception {
System.out.println("RegisterSuccesssControl called");
//logger.debug("Registration Page Accessed at "+new Date());
System.out.println("I am In registerSuccess");
RegistrationValidator uValidator=new RegistrationValidator();
uValidator.validate(register,brResult);
HashMap<String, BindingResult> resultMap = new HashMap<String, BindingResult>();
if(brResult.hasErrors()){
resultMap.put("errors", errors);
return new ModelAndView("Register",resultMap);
}
else
return new ModelAndView("Firm");
}
I have other request handled in same controller and its working fine, but its not working for this link.

Resources