Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests().antMatchers("/SC_A99_01_LoginIni").permitAll();
http.authorizeRequests().antMatchers(HttpMethod.POST, "/SC_A01_01_MasterRegisterEmployeeImport")
.access("hasRole('0')");
http.authorizeRequests().and().exceptionHandling().accessDeniedPage("/403");
http.authorizeRequests().and().formLogin()
// Submit URL
.loginProcessingUrl("/SC_A99_01_Login")
.loginPage("/SC_A99_01_LoginIni")
.defaultSuccessUrl("/SC_A99_01_Login")
.failureUrl("/SC_A99_01_Login")
.usernameParameter("loginId")
.passwordParameter("password");
http.authorizeRequests().and() //
.rememberMe().tokenRepository(this.persistentTokenRepository()) //
.tokenValiditySeconds(1 * 24 * 60 * 60); // 24h
}
When I login success or error then it return a controller /SC_A99_01_Login with method GET, but i want return method POST
As both defaultSuccessUrl and failureUrl are defined for redirect, that means a new request will be made from the web browser after successful login or failure login.
.defaultSuccessUrl("/SC_A99_01_Login")
.failureUrl("/SC_A99_01_Login")
And if you don't want to make a new GET request from web browser, you can try another set
.successForwardUrl("/SC_A99_01_Login")
.failureForwardUrl("/SC_A99_01_Login")
which it will not make the web browser to send another request, but forward the same context to the new URL.
Related
I have a "customer detail" form that submits a POST request. This is in a Spring Boot application and is implemented as a Thymeleaf template. I have just added a little AJAX function to the form -- when the user clicks a certain button, it uses jQuery.ajax() to look up a geo-code based on the customer's address. The AJAX call is a GET request.
If I enter the customer form and click "Submit" without touching the Ajax button, it submits normally. But if I use the Ajax button first, and then try to submit the form, it gets stopped by the CsrfFilter with a message "Invalid CSRF token found for http://...".
I assume that the Ajax call is somehow making the CSRF token expire, so that a new one is needed, but how can I prevent that?
There are some similar-sounding questions like this one but in that case they're looking for a way to add a CSRF token to an Ajax request. Also, I'm using Thymeleaf views so I get the CSRF token automatically inserted into my form -- I don't have to add it manually.
The problem was that I had implemented a custom filter to delete the security context on every request. This was my way of making the application stateless, as I documented in this software engineering SE answer. That deletes (or resets?) the server-side CSRF token so it won't match the one in the form, however, the custom filter fires after the CsrfFilter so I never had a problem with form submission before.
In this case though I have Ajax requests that are handled after the form is built for the client but before it is submitted, so my custom filter's unfortunate side effect causes form submission to fail.
I corrected it by modifying the custom filter to skip deleting the context if the URL is under a particular directory path:
public class SecurityContextDeletingFilter extends GenericFilterBean {
RequestMatcher exceptedPaths = new AntPathRequestMatcher("/form-ajax/**");
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) servletRequest;
final HttpSession session = request.getSession();
if( exceptedPaths.matches(request)) {
// Deleting the security context deletes the CSRF token in the session. We want to make sure this
// does NOT occur if the user is in a form and is using Ajax features like the geocode lookup,
// because they'll need the server to recognize the token on eventual form submission.
logger.trace("Skipping this filter for a /form-ajax/ endpoint.");
} else {
if( session.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY) != null ) {
session.removeAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
}
}
filterChain.doFilter(servletRequest,servletResponse);
}
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I am using Laravel's FormRequest for validation to make my code clean in controller and after validation, I want to add some data to request and then save it. So, I was just looking for a solution so that I do not have to add data to request in controller If just after validation in the same file there could be the extra function for modifying data and send to controller. It would have been better.
If you want to do something with request after it validated, you can use After Validation Hook, as apokryfos suggested.
But I think it is a bit more convinient to put that hook inside of your FormRequest descendant class.
Ancestor:
use Illuminate\Foundation\Http\FormRequest;
class AncestorRequest extends FormRequest
{
...
protected function getValidatorInstance()
{
return parent::getValidatorInstance()->after(function ($validator) {
$this->after($validator);
});
}
protected function after($validator)
{
//
}
}
Descendant:
class DescendantRequest extends AncestorRequest
{
...
public function after($validator)
{
// do your things
}
}
P. S. This solution I am using in Laravel 5.2. Here you can find more options.
Is there a specific reason why a user sign-in with {providerId} can only be initiated with a POST request (to /signin/{providerId})? Why not with a GET request?
Answering my own question: Maybe because of
/**
* Process the authentication callback when neither the oauth_token or code parameter is given, likely indicating that the user denied authorization with the provider.
* Redirects to application's sign in URL, as set in the signInUrl property.
* #return A RedirectView to the sign in URL
*/
#RequestMapping(value="/{providerId}", method=RequestMethod.GET)
public RedirectView canceledAuthorizationCallback() {
return redirect(signInUrl);
}
Anyway, it would be nice if a sign-in with a GET request would be possible, too (with a different URL or a parameter narrowing the mapping).
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
Error throwing while sending an email using laravel after migration the web application to a new server. It was working fine on the previous server.
Relevant error description edited in from comments:
[2018-01-25 13:31:10] production.ERROR: ErrorException: mkdir(): No
such file or directory in
/var/www/html/jbservice/vendor/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache/Disk$
Stack trace: #0 [internal function]:
Illuminate\Foundation\Bootstrap\HandleExceptions->handleError(2,
'mkdir(): No suc...', '/var/www/html/j...', 273, Array) #1
/var/www/html/jbservice/vendor/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache/DiskKeyCache.php(273):
mkdir('/tmp/68d392a3e3...')
Relevant code edited from comments:
Mail::send('dashboard.emails.createticket', $data , function ($message)
use ($data) { $message->subject('New Ticket: ' . $data['subject'])
->to("atif#gmail.com")
->from('HERE COMES THE SENDER EMAIL'); });
You can check your log.
If it show the SwiftMailer was trying to create cache in default /tmp folder :
To solve the issue, change the TMPDIR environment variable in the boot() method of app/Providers/AppServiveProvider.php.
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
/**
* Somehow PHP is not able to write in default /tmp directory and SwiftMailer was failing.
* To overcome this situation, we set the TMPDIR environment variable to a new value.
*/
if (class_exists('Swift_Preferences')) {
\Swift_Preferences::getInstance()->setTempDir(storage_path().'/tmp');
} else {
\Log::warning('Class Swift_Preferences does not exists');
}
}
Please make sure that the new “tmp” folder location is writable by the web server.
I am using AuthorizeAttribute to ensure that my controller actions aren't ran when the current user is unauthorized. This works great for GET requests. If the user is not authorized then they are redirected to the login view.
However, this does not work for POST requests as the browser isn't expecting to be redirected during a POST.
The generally agreed upon solution to this is to disallow users from reaching portions of the application which generate POST requests without first being authorized. While this logic makes sense, I don't think it encompasses all real world scenarios.
Consider having the web application open in two tabs. The user is signed in and authorized in both tabs and is viewing content which, when clicked, could initiate a POST request. The user then signs out of one tab and is taken back to the login page. The other tab is unaware that this event has occurred. The user then initiates a POST request from this second tab.
How can I gracefully redirect them to the login page in this scenario?
I believe you are incorrect. I have a custom blog (that still needs a ton of work) which I use the [Authorize] attribute on the Admin controller. This controller handles blog post.
I tested your scenario of:
Opening up two browser screens on my post screen
logging out in the first tab
Attempting to post on the second tab
when it tried to post it redirected me to the login screen.
[Authorize]
public class AdminController : BaseController
{
public ActionResult Post(int? id)
{
if (id != null)
{
var blogPost = _blogService.RequestPost((int)id);
var blogPostViewModel = _blogPostViewModelMapper.CreateViewModel(blogPost);
return View(blogPostViewModel);
}
return View();
}
//
// POST: /Post/
[HttpPost]
public ActionResult Post(BlogPostViewModel blogPost)
{
var stringTags = blogPost.Tags.Split(',');
var tagIds = _blogTagMapper.MapStringsToIds(stringTags);
blogPost.TagIds = tagIds;
_blogService.SaveBlogPost(BlogPostlMapper.CreateEntity(blogPost));
return RedirectToAction("Index", "Home");
}
}