I have a spring mvc web app that has an API, that looks like this
/api/createUser?name=Tom.
At the same time there is a web site backed by the same web app, that has restricted pages, which can only be accessed once the a user authorizes using login form + Active Directory. I have managed to set up AD and it works well, but I am kinda lost with the API.
I want to make an authentication for API calls too. Namely, I want to introduce username and password fields to every API call, so that when the relevant controller receives this API call, it first authenticates the user programmatically and it succeeded, then proceeds further with the request.
So the question is, how can I authenticate a user programmatically outright from MVC controller in Spring? Is there any magic bean that I can inject and harness its power?
I think you could use spring sercurity
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<http auto-config="true">
<intercept-url pattern="/api**" access="ROLE_USER" />
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="username" password="password" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
Related
I have following code for spring security but it does not work. When I open log-in page and enter username/password which is admin#myproject.com / secret, following error message will be shown. Once username/password are entered following with be added to the address ?error=1, even if I remove it manually and refresh the page message does not go. Nothing is shown in console.
Your login attempt was not successful due to
Bad credentials.
spring-security.xml
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<beans:import resource='login-service.xml' />
<http auto-config="true" access-denied-page="/notFound.jsp"
use-expressions="true">
<intercept-url pattern="/" access="permitAll" />
<intercept-url pattern="/member**" access="hasRole('ROLE_MEMBER')" />
<form-login login-page="/signin" default-target-url="/index"
authentication-failure-url="/signin?error=1" />
<logout logout-success-url="/login?logout" />
<csrf />
</http>
<authentication-manager>
<authentication-provider>
<user-service> <user name="admin#myproject.com" password="secret"
authorities="ROLE_ADMIN"/>
<user name="user#yahoo.com" password="secret" authorities="ROLE_USER"/>
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
The form has following code, it seems like SPRING_SECURITY_LAST_EXCEPTIONis not empty even before submitting the form.
<c:if test="${not empty SPRING_SECURITY_LAST_EXCEPTION}">
<font color="red"> Your login attempt was not successful due
to <br />
<br /> <c:out value="${SPRING_SECURITY_LAST_EXCEPTION.message}" />.
</font>
</c:if>
<form id="form-login" role="form" method="post"
action="<c:url value='/j_spring_security_check' />"
class="relative form form-default">
<input type="hidden" name="${_csrf.parameterName}"
value="${_csrf.token}" />
I am not sure why, but the same code returns following error now
Your login attempt was not successful due to
Authentication method not supported: GET.
You need to allow everyone to access your /signin page, even if he is not authenticated.
<intercept-url pattern="/signin" access="permitAll" />
I wrote this answer before the question was changed the first time, at a time where the question was (it is still the title): "Spring-security shows 'Bad Credentials' even before submitting the form"
<intercept-url pattern="/member**" access="hasRole('ROLE_MEMBER')" />
<user name="user#yahoo.com" password="secret" authorities="ROLE_USER"/>
Above configs have two different Role names ROLE_MEMBER and ROLE_USER
UPDATE
Since Authentication method not supported: GET, can you try allowing GET.
<bean id="authenticationFilter"
class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"
p:postOnly="false" />
And the following change is also required in web.xml
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
Hope this helps
The SPRING_SECURITY_LAST_EXCEPTION stays in the session even if you refresh the page. You need check for the error parameter:
<c:if test="${(not empty param.error) && (not empty SPRING_SECURITY_LAST_EXCEPTION)}">
I guess your login controller method is doing redirect or forward, and then tries to send a HTTP GET request to the login URL with the user name and password as query parameters. It is generally considered bad practice to send credentials as URL parameters and that's why is not allowed. It be should send a HTTP POST instead.
If you will want to stay with GET, you could bypass the check by using a request wrapper which returns HTTP POST instead of HTTP GET for getMethod.
Updated answer from #tharingu_DG should work, but it is still technically equivalent to sending unencrypted authentication credentials since anyone who steals it can use it to authenticate.
Newbie to Spring security. I had gone through some tutorials and implemented Spring Security. I have few pages which I secured via login.
Here is my spring-security.xml file
<?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"
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" use-expressions="true">
<security:intercept-url pattern="/person*/*"
access="hasRole('ROLE_ADMIN')" />
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="admin" password="password"
authorities="ROLE_ADMIN" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
From my index.jsp, when I try to access persons URL, it's asking for authentication. And I have logout URL. Inside persons JSP page.
<a href="<c:url value="logout" />" > Logout</a>
Controller
#RequestMapping(value = "/logout", method = RequestMethod.GET)
public ModelAndView logoutPage(HttpServletRequest request, HttpServletResponse response) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null) {
new SecurityContextLogoutHandler().logout(request, response, auth);
}
return new ModelAndView("redirect:/");
}
It's working fine. Except few things. - When I try to go to /person/add, it's directly going to the page instead of asking the Authentication. Why? and how to resolve? Do I need to mention all URLs in intercept URLs (What if I have many?)
Well the main thing is, I'm trying to configure SSL as well for my application.
I installed this tutorial.
I have created ketstore
Configured in tomcat, server.xml
Configured in web.xml
Now I have the following in spring-security.xml
<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/**"
requires-channel="https" />
<security:intercept-url pattern="/person*/*"
access="hasRole('ROLE_ADMIN')" />
</security:http>
The SSL is working. But Login is not working. When I go to persons URL, it's showing the page without asking for authentication. Why?
I tried adding access=hasRole('ROLE_USER'), then tomcat is showing Access denied when I give correct credentials.
How to solve it? I want to enable SSL for all URLs.
I'm using Spring 4.2.2.RELEASE and Spring Security 4.0.2.RELEASE
First, try to rewrite your security:intercept-url as following:
<security:intercept-url pattern="/person*" access="hasRole('ROLE_ADMIN')" />
<security:intercept-url pattern="/person/**" access="hasRole('ROLE_ADMIN')"
Regarding SSL, the tutorial is very nice and it should work out of the box, maybe the problem is again with intercepting url's, try my suggestion.
I am trying to add a custom filter to the spring security configuration. But the problem is that whenever I try to add the filter using xml I am getting an exception saying that
"Configuration problem: Filter beans '< subdomainFilter >' and '< org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#1 >' have the same 'order' value. When using custom filters, please make sure the positions do not conflict with default filters. Alternatively you can disable the default filters by removing the corresponding child elements from and avoiding the use of < http auto-config='true' >."
I am adding my spring security configuration below
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<beans:bean id="subdomainFilter" class="com.testbudha.security.authentication.UsernamePasswordAuthenticationFilterWithSubdomain"/>
<http pattern="/**" auto-config='false' use-expressions='true'>
<custom-filter position="FORM_LOGIN_FILTER" ref="subdomainFilter" />
.......
</http>
........
</beans:beans>
Spring Security maintains a chain of filters in order to apply its services. The order of the filters is always strictly enforced when using the namespace. When the application context is being created, the filter beans are sorted by the namespace handling code and the standard Spring Security filters each have an alias in the namespace and a well-known position.
Your <form-login> is using a filter with alias FORM_LOGIN_FILTER. And also you are adding another filter with the same position (position="FORM_LOGIN_FILTER" ref="subdomainFilter"). So you're getting the error message
Try using
<custom-filter after="FORM_LOGIN_FILTER" ref="subdomainFilter" />
or
<custom-filter before="FORM_LOGIN_FILTER" ref="subdomainFilter" />
We are developing a Spring based web application, which is using Spring Security 3.2.3. We are integrating with an external payment gateway (Paytm) for accepting user's payments. Following is a scenario where we are facing issue:
User logs in to the application (it's an HTTP non-S app) and clicks on a button which
redirects him to the payment gateway (Paytm payment gateway - it's HTTPS url).
For Paytm integration, we have configured a callback URL i.e. index page of our application (eg. http://server:port/app/index.jsp). User completes the payment and Paytm redirects the control back to our Spring application.
When Paytm tries to call our app's index page (eg. http://server:port/app/index.jsp), it fails and in Chrome debugger, we could see a 403 Forbidden response.
However, this scenario works well in Mozilla Firexfox and IE 11. The issue in only seen in Google Chrome and Operabrowsers.
We tried by providing some other website in callback URL (like https://google.com) and the redirection went successful.
What we are suspecting is it might be some config issue or missing setting in Spring Security, but which we are not sure of.
This is our Spring Security config:
<http auto-config="true" use-expressions="true">
<!-- Un-comment when authorization is implemented -->
<intercept-url pattern="/**" access="isAuthenticated()"/>
<form-login authentication-failure-handler-ref="failureHandler"
authentication-success-handler-ref="successHandler" />
<intercept-url pattern="/**" />
<logout logout-success-url="${login.page.url}" />
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider>
<password-encoder ref="encoder" />
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query="select gu.email, gu.password, gu.enabled from global_user gu,global_organization_user gou, global_organization go where email=? and gu.enabled=1 and gu.is_deleted=0 and gou.user_id = gu.id and gou.organization_id=go.id and go.current_stage='ACTIVE' and go.is_deleted=0"
authorities-by-username-query="select u.email, r.role_id from global_user u, security_user_role r
where u.id = r.user_id and u.email=?" />
</authentication-provider>
</authentication-manager>
<beans:bean id="encoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
<beans:bean id="successHandler"
class="app.server.security.authentication.AuthenticationSuccessHandler" />
<beans:bean id="failureHandler"
class="app.server.security.authentication.AuthenticationFailureHandler" />
<beans:bean id="expressionHandler"
class="app.server.security.authorization.CustomMethodSecurityExpressionHandler">
<beans:property name="permissionEvaluator" ref="authorizationEvaluator">
</beans:property>
</beans:bean>
<beans:bean id="authorizationEvaluator"
class="app.server.security.authorization.AuthorizationEvaluator" />
<global-method-security pre-post-annotations="enabled">
<expression-handler ref="expressionHandler" />
</global-method-security>
<http pattern="/rest/app/someurl**" security="none"/>
// other URLs which are escaped from spring security
Any suggestions and pointers are appreciated.
This issue is temporarily solved by redirecting the payment gateway response to an intermediate URL (we created a separate web project and provided its link). This intermediate URL then redirects the control to our Spring application.
Faced similar issue as op, but we managed to fix this by configuring our callback URL to use https instead of http. However, this might not work for everyone since every payment gateway has different security control. Hopefully this helps!
This problem also solved at my site at localhost using https.
Add SSL certificate and try it.
Soory for disgusting you. Actually i am poor in english. I am developing a spring application by using google app engige.
1. If the server is in running mode, for the first if i would try to log into the application. Firstly it should navigate to the
login page.
2. If any user wants to access aby page in the application by giving the page name like for example(in my application if i have ABC.jsp page, if the user wnat to access the file by giving 127.0.0.0:8888/ABC.jsp) it should navigate to the some default page which contains some message, and click here to navigate to the home page.
Now can you please tell how to do it in my application.
can you please tell me the step by step process to achieve this by using Spring MVC ,Objectify ORM and Google app engine.
Still don't quite understand what your problem is.
Add this to your web.xml:
<welcome-file-list>
<welcome-file>/login</welcome-file>
</welcome-file-list>
</web-app>
This ensures that if a user only types http://server:port she is redirected to http://server:port/login.
Now if you want that the user is also redirected to login if she types http://server:port/foobar.html, what you call "random page", which does not exist then you need an HTTP status code mapping.
<error-page>
<error-code>404</error-code>
<location>/login</location>
</error-page>
If you want that the user must always first authenticate (i.e. go through /login) first before any existing page is displayed you could use Spring Security for that. Example for simple basic-auth:
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.3.xsd">
<!-- HTTP basic authentication in Spring Security -->
<http>
<intercept-url pattern="/*" access="ROLE_USER" />
<http-basic />
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="user" password="password" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
You can use spring security to do this. Have a look at
this link. The http tag should allow this. It will direct a user the login page for users that aren't authenticated. A sample context would be the following.
<beans:bean id="loginUrlAuthenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:property name="loginFormUrl" value="/jsp/login.jsp" />
</beans:bean>
<http auto-config="false" use-expressions="true" entry-point-ref="loginUrlAuthenticationEntryPoint">
<intercept-url pattern="/protected" access="hasRole('ROLE_protected')" />
<intercept-url pattern="/jsp/login.jsp*" filters="none"/>
<logout logout-success-url="/jsp/login.jsp" invalidate-session="true" />
<session-management invalid-session-url="/jsp/login.jsp?timeout=true" />
</http>