I have two tables in this project of mine. One table is for the site admin which stores all the admin users details, and the other table stores all the login data for clients to the site.
At the moment, I can log in using the admin details fine. However, I am now trying to login with the client details and it doesn't seem to be working. So far, when a user clicks on a link it will go to /clientarea/login. This page loads up fine. But when I try to log in I get an error.
The error I am getting is this:
Unable to find the controller for path "/clientarea/login_check". Maybe you forgot to add the matching route in your routing configuration?
In my security.yml file, I have the following code: (By the way, I'm using plaintext for development only, it will be changed when it goes live):
providers:
admin_db:
entity: { class: Shout\AdminBundle\Entity\User, property: username }
client_db:
entity: { class: Shout\AdminBundle\Entity\Userclients, property: username }
encoders:
Shout\AdminBundle\Entity\User:
algorithm: plaintext
Shout\AdminBundle\Entity\Userclients:
algorithm: plaintext
firewalls:
secured_area:
pattern: ^/
anonymous: ~
provider: admin_db
form_login:
check_path: /login_check
login_path: /login
logout:
path: /logout
target: /index
client_area:
pattern: ^/
anonymous: ~
provider: client_db
form_login:
check_path: /clientarea/login_check
login_path: /clientarea/login
logout:
path: /clientarea/logout
target: /index
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin, roles: ROLE_ADMIN }
- { path: ^/clientarea/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/clientarea, roles: ROLE_USER }
In my routing.yml I have this code:
login:
pattern: /login
defaults: { _controller: ShoutAdminBundle:Security:login }
login_check:
pattern: /login_check
logout:
pattern: /logout
clientlogin:
pattern: /clientarea/login
defaults: { _controller: ShoutAdminBundle:Security:clientlogin }
clientlogin_check:
pattern: /clientarea/login_check
clientlogout:
pattern: /clientarea/logout
Here is the code in the controller. The code is identical for the login and clientlogin functions, the only thing that is different is the twig file they point to:
$request = $this->getRequest();
$session = $request->getSession();
// get the login error if there is one
if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
$error = $request->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
} else {
$error = $session->get(SecurityContext::AUTHENTICATION_ERROR);
}
return $this->render('ShoutAdminBundle:Security:clientlogin.html.twig', array(
// last username entered by the user
'last_username' => $session->get(SecurityContext::LAST_USERNAME),
'error' => $error,
));
The action path of the Client Login form points to clientlogin_check.
What am I doing wrong?
I've managed to get it working, but in a very basic way. I don't have time due to a deadline to make the login pages pretty looking.
But here is the code:
client_area:
pattern: ^/clientarea
anonymous: ~
provider: client_db
http_basic:
realm: "Secured Client Area"
Basically, you can have users from more than one table. However, I have still been unable to make it work using a proper login form. But the basic HTTP login box works just as well for what I'm doing.
Related
I've built a web app using Symfony 2.8 and I've now got to the task of separating the admin area from the front end. I have done that using the following code in the security.yml file:
security:
encoders:
MyApp\Bundle\CoreBundle\Entity\Users:
algorithm: sha512
role_hierarchy:
ROLE_ADMIN: ROLE_BLOCKED
providers:
main:
entity: { class: MyApp\Bundle\CoreBundle\Entity\Users, property: username }
firewalls:
default:
anonymous: ~
secured_area:
pattern: ^/admin
anonymous: ~
access_denied_url: core_login
form_login:
check_path: core_login_check
login_path: core_login
failure_path: core_login
default_target_path: ^/admin/booking/today/
logout:
path: core_logout
target: core_login
access_control:
- { path: ^/admin, roles: 'ROLE_ADMIN' }
- { path: ^/ajax/admin, roles: 'ROLE_ADMIN' }
- { path: ^/ajax/backend, roles: 'ROLE_ADMIN' }
- { path: ^/, roles: 'IS_AUTHENTICATED_ANONYMOUSLY' }
This is working for me in terms of blocking access to the areas I want. However, if the anonymous user tries to access /admin I get the following message:
Full authentication is required to access this resource.
When I do this in the production environment, I just get the standard 500 error.
What I want to have happen is the user be redirected to the login page. This isn't happening at the moment, so what can I do to acheive this?
In my Symfony2 project i have a logout button which redirect to the index page but when i click the Login button it connects directly without asking me for user and password.
how can i validate all session attributes, so if i login again it should ask me for user and password
this is my logout Action:
public function logoutAction(Request $request)
{
$this->get('security.context')->setToken(null);
$this->get('request')->getSession()->invalidate();
$url = $this->generateUrl('my_route');
$response = new RedirectResponse($url);
$response->headers->clearCookie('PHPSESSID');
$response->send();
return $response;
}
here's the security.yml:
security:
encoders:
Envivio\UserBundle\Entity\User: sha512
role_hierarchy:
ROLE_USER: ROLE_USER
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH ]
providers:
mine:
id: ib_user.oauth_user_provider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: true
pattern: ^/
oauth:
resource_owners:
salesforce: "/login/check-salesforce"
login_path: /login
#use_forward: false
failure_path: /login
default_target_path: /upload
oauth_user_provider:
service: ib_user.oauth_user_provider
remember_me:
key: "%secret%"
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin, role: ROLE_ADMIN }
You can try :
$this->get('session')->clear();
or
$session = $this->get('session');
$ses_vars = $session->all();
foreach ($var as $key => $value) {
$session->remove($key);
}
It may also be a cookie problem check your cookies in the response->headers then try clearing it with that function :
http://api.symfony.com/2.3/Symfony/Component/HttpFoundation/ResponseHeaderBag.html#method_clearCookie
Edit :
Since you have remember me enabledyou need to clear that cookie too otherwise the next request you do will reauthenticate the user, you can specify a name for the cookie :
#security.yml
remember_me:
name: "%session.remember_me.name%"
add in parameters.yml the name of the cookie
parameters:
session.remember_me.name: EXTSESS
then in your controller logout action :
$response = $this->redirectToRoute('homepageroute'); //redirect prepare the route to redirect
$this->get('security.context')->setToken(null);
$this->get('request')->getSession()->invalidate();
$remember_sess_name = $this->container->getParameter('session.remember_me.name');
$response->headers->clearCookie($remember_sess_name);
return $response;
it should work now. if this doesn't then ALT+F4 :D
You don't need to do it manually. The Symfony2 firewall can perform a logout like this:
# app/config/security.yml
security:
firewalls:
secured_area:
# ...
logout:
path: /logout
target: /
# ...
Next, you'll need to create a route for this URL (but not a
controller):
# app/config/routing.yml
logout:
path: /logout
And that's it! By sending a user to /logout (or whatever you configure
the path to be), Symfony will un-authenticate the current user.
Once the user has been logged out, they will be redirected to whatever
path is defined by the target parameter above (e.g. the homepage).
Link to the related doc: http://symfony.com/doc/current/book/security.html#logout
In my symfony project, I would like to use authentification.
So I wrote this in my security.yml file
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
default:
anonymous: ~
login_firewall:
pattern: ^/login$
anonymous: ~
secured_area:
pattern: ^/
anonymous: ~
form_login:
login_path: /login
check_path: /login_check
post_only: true
always_use_default_target_path: true
default_target_path: /
use_referer: false
username_parameter: username
password_parameter: password
intention: authenticate
logout:
path: /logout
target: /
Ok, now documentation says that I need to add in routing.yml this :
login:
pattern: /login
defaults: { _controller: AcmeSecurityBundle:Security:login }
login_check:
pattern: /login_check
But I am using annotation, so I don't use routing files. Instead I have this :
/**
* #Route("/login")
* #Template()
*/
public function loginAction()
{
$request = $this->getRequest();
$session = $request->getSession();
// get the login error if there is one
if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
$error = $request->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
} else {
$error = $session->get(SecurityContext::AUTHENTICATION_ERROR);
$session->remove(SecurityContext::AUTHENTICATION_ERROR);
}
return array(
// last username entered by the user
'last_username' => $session->get(SecurityContext::LAST_USERNAME),
'error' => $error,
);
}
If I do nothing, I have an error in my login page :
"Unable to generate a URL for the named route "login_check" as such route does not exist."
If I add an action in my controller with an empty response, there is... nothing.
What am I doing wrong ?
login_check or whatever you specify is system defined route and not an action. That means that you can not/shall not/will not define it manually in controller. ;)
I myself use annotations to do routing but, one way or another, you will use routing.yml in order to import your controllers and thus annotated routes from within them.
So, go ahead, just define that route in your routing.yml and it should work.
I'm trying to restrict users from going to anything within /admin/ and if they attempt to then they will be redirected to /login.
At the moment I can get to the login page which is using a traditional login form and if I submit it I get an error returned saying 'Bad Credentials', therefore the /login_check seems to be working correctly. However, if I go to /admin/ or /admin/foo it doesn't redirect to /login. Instead it says 'No route found for GET /admin/'.
My security.yml file is:
jms_security_extra:
secure_all_services: false
expressions: true
security:
encoders:
Symfony\Component\Security\Core\User\User: plaintext
role_hierarchy:
ROLE_ADMIN:
ROLE_SUPER_ADMIN:
providers:
administrators:
entity: { class: XXXBundle:AdminUser, property: email }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
admin_area:
pattern: ^/admin
form_login:
login_path: /login
check_path: /admin/login_check
#anonymous: ~
#http_basic:
# realm: "Secured Demo Area"
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
My routing.yml file is:
login:
pattern: /login
defaults: { _controller: XXXBundleSecurity:login }
login_check:
pattern: /admin/login_check
/admin/XXX routes are unneccessary. If you have set
pattern: ^/admin
/admin/XXX should be redirected to /login.
more details see http://symfony.com/doc/2.0/book/security.html#using-a-traditional-login-form
It seems you're missing both routes you're trying to access. Try to add this to your routing.yml:
admin:
resource: "#XXXBundle/Controller/Admin.php"
type: annotation
prefix: /admin
I like Routes using Annotations very much so I used that in this example.
Then in your Admin.php you can use something like:
// XXXBundle/Controller/Admin.php
namespace XXXBundle/Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Request;
class AdminController extends Controller
{
/**
* #Route("/", name="admin_index")
*/
public function indexAction(Request $request)
{
// Code goes here
}
/**
* #Route("/foo ", name="admin_foo")
*/
public function fooAction(Request $request)
{
// Code goes here
}
}
After login failure, the application does not redirect to the login page.Here is my security.yml configuration:
security:
encoders:
Acme\SecurityBundle\Entity\Users: sha512
role_hierarchy:
ROLE_ADMIN: ROLE_USER
providers:
main:
entity: { class: Acme\SecurityBundle\Entity\Users}
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/login$
security: false
secured_area:
pattern: ^/admin/
form_login:
check_path: /login_check
login_path: /login
logout:
path: /logout
target: /home
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
Here is my controller:
class LoginController extends Controller {
/**
* #Route("/login",name="login")
*/
public function loginAction() {
//displays login form and renders the login.html.twig
}
/**
* #Route("/login_check", name="login_check")
*/
public function loginCheckAction() {
// The security layer will intercept this request
}
After login failure I get error as :
The controller must return a response (null given). Did you forget to add a return statement somewhere in your controller?
500 Internal Server Error - LogicException
I tried the login section inside the Demo that ships with symfony. I found the same result.
What modification should I have to make in order redirect to login form after login failure ?
You don't need to create a controller class for the login and logout actions. You just need to specify those routes inside of routing.yml, something like:
login_path:
pattern: /login
login_check_path:
pattern: /admin/login_check
logout_path:
pattern: /admin/logout
These routes are automatically handled by the security component.
In the firewall configuration, your check_path should be defined as /admin/login_check. The logout path should be /admin/logout.