How to manipulate session in spring mvc . I have searched in the network and I found that Spring MVCcould be the solution. But the problem is I can only pass two parameters of authentification (the username and the password)
<user-service>
<user name="user" password="123456" authorities="ROLE_USER" />
</user-service>`
and in my case I must pass three parameters.I would be so grateful if I found the solution in this forum.
Related
Greeting everyone, I try to configure simple authorization code flow via Spring Security OAuth.
I tested my authorisation and resource server configuration via following approaches:
Create a web application as client and use its page to fire http post call to /oauth/authorize.
After getting code, I use the same page to
fire another http post with code and get token.
At the end, I use
curl -H to place token inside header and get response from protected
resource.
But when I try to use rest template. It throw error message 401 Unauthorised error.
Server side - security configure:
<http auto-config="true" pattern="/protected/**"
authentication-manager-ref="authenticationManager">
<custom-filter ref="resourceFilter" before="PRE_AUTH_FILTER" />
<csrf disabled="true" />
</http>
<http auto-config="true">
<intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
<form-login default-target-url="/admin.html" />
<logout logout-success-url="/welcome.html" logout-url="/logout"/>
<csrf disabled="true" />
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider>
<user-service>
<user name="admin" password="123456" authorities="ROLE_USER,ROLE_ADMIN" />
</user-service>
</authentication-provider>
</authentication-manager>
Server side - authorisation and resource configure:
<oauth:authorization-server
client-details-service-ref="clientDetails" error-page="error">
<oauth:authorization-code />
</oauth:authorization-server>
<oauth:client-details-service id="clientDetails">
<oauth:client client-id="admin" secret="fooSecret" />
</oauth:client-details-service>
<oauth:resource-server id="resourceFilter" />
Client Side:
<oauth:client id="oauth2ClientContextFilter" />
<oauth:resource id="sso" client-id="admin"
access-token-uri="http://localhost:8080/tough/oauth/token"
user-authorization-uri="http://localhost:8080/tough/oauth/authorize"
use-current-uri="true" client-secret="secret"
client-authentication-scheme="header" type="authorization_code"
scope="trust" />
<oauth:rest-template id="template" resource="sso"/>
If anyone knows where goes wrong, please do let me know.
There were two issues with my configuration above.
I noticed my client used wrong secret to communicate with authorization server.
Token endpoint at authorization server use authentication manager which
serve user authentication. It result
client are rejected all times until I create new security realm for
token endpoint and configure it to use a authentication manger designed for
client.
Note client is different from user. Client is third party want to access resource belong to your user (also called resource owner).
I had the same problem. It helped to add a
org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService
to spring securities authentication-manager, glueing the clientDetailsService to the authentication manager. So
<authentication-manager alias="authenticationManager">
...
<authentication-provider user-service-ref="clientDetailsUserDetailsService"/>
...
</authentication-manager>
nearly solved the problem for me. I had one more Issue: Since ClientDetailsUserDetailsService has no default constructor, spring threw Exceptions of the form
org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class
[class org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService]:
Common causes of this problem include using a final class or a non-visible class;
nested exception is java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
Which I could not solve without using a copy of that class receiving the clientDetailsService as property instead of a constructor arg.
I'm new to Spring (and to web development in general), but I've managed to create a simple web application and now I'm trying to add authentication support to it so that users are required to sign in to access its features.
I'm using Spring MVC 3.2.2, Spring Security 3.1.4, and Tomcat 7.
For testing purposes, I was able to add authentication support using hardcoded users and everything worked correctly. Now, I must use an existing PostgreSQL database to authenticate users. I would like to emphasize that my application does not support the creation of users; users are already stored in the database.
The following is the problem:
(1) The application must authenticate users against a PostgreSQL database, which I cannot modify in any way.
(2) Passwords in the database are hashed using crypt('plain text password', gen_salt(md5)).
(3) Since I've made heavy use of annotations and xml configuration, basically most of the hard work is done by Spring, which means that a lot of things are going on behind the scenes, which I'm not aware of. As a result, I'm now stuck setting up the salt the password encoder must use to authenticate the users. Such a salt has to be the already hashed password stored in the database.
The question is:
How do I tell Spring Security to use the hashed password stored in the database as the salt of the password encoder? Is there any way to do this from xml or do I need to go ahead and implement certain class(es)?
I've searched extensively on-line and all of the examples I've found so far deviate considerably from what I have done, mainly because in the examples most of the functionally is implemented by the developer instead of mostly relying on built-in features.
This is the security.xml file:
<http use-expressions="true">
<intercept-url pattern="/resources/images/**" access="permitAll" requires-channel="any"/>
<intercept-url pattern="/resources/css/**" access="permitAll" requires-channel="any"/>
<intercept-url pattern="/login*" access="permitAll" requires-channel="any"/>
<intercept-url pattern="/**" access="hasAnyRole('ROLE_Processer', 'ROLE_Verifier', 'ROLE_Approver', 'ROLE_Supervisor', 'ROLE_Admin')" requires-channel="any"/>
<session-management>
<concurrency-control max-sessions="1" expired-url=/login?expired=true" session-registry-alias="sessionRegistry"/>
</session-management>
<form-login
login-page="/login"
default-target-url="/"
always-use-default-target="true"
authentication-failure-url="/login?error=true"/>
<logout logout-success-url="/login" invalidate-session="true" delete-cookies="JSESSIONID"/>
</http>
<authentication-manager>
<authentication-provider>
<jdbc-user-service
data-source-ref="dataSource"
users-by-username-query="SELECT id AS username, password, enabled FROM users WHERE id=?;"
authorities-by-username-query="SELECT id AS username, role FROM users WHERE id=?;"
role-prefix="ROLE_"/>
<password-encoder hash="md5">
<salt-source ???/>
</password-encoder>
</authentication-provider>
</authentication-manager>
This is the relevant excerpt from the web.xml file:
<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>
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>
This is the relevant excerpt from the application-context.xml file:
<beans:bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
<beans:property name="driverClass" value="org.postgresql.Driver"/>
<beans:property name="url" value="jdbc:postgresql://host:port/database"/>
<beans:property name="username" value="username"/>
<beans:property name="password" value="password"/>
</beans:bean>
In terms of implementation, this is the only relevant controller LoginController.java (all others handle the actual functionality provided by the app):
#Controller
public class LoginController {
private static final Logger LOGGER = LoggerFactory.getLogger(LoginController.class);
/**
* Displays the Login form.
*/
#RequestMapping(value="/login", method=RequestMethod.GET)
public String displayLoginForm(#RequestParam(value="error", required=false) String error, #RequestParam(value="expired", required=false) String expired, Model model) {
LOGGER.info("Displaying Login form:: displayLoginForm(Model)");
if (error != null) {
LOGGER.info("Invalid username or password.");
model.addAttribute("error", "Invalid username or password.");
}
if (expired != null) {
LOGGER.info("Session has been expired (possibly due to multiple concurrent logins being attempted as the same user)");
model.addAttribute("expired", "Session has been expired (possibly due to multiple concurrent logins being attempted as the same user).");
}
return "login";
}}
Any pointers will be greatly appreciated. I would like to thank you all in advance for your time and help.
Edit:
I tried with
<password-encoder hash="md5">
<salt-source user-property="password"/>
</password-encoder>
since, from what I understood by reading the documentation, this is the user's password stored in the database. However, it doesn't work. Every time I try to log in, I get an invalid credentials message; however, the credentials are indeed valid.
Perhaps any of the events described in the Hashing and Authentication section of this page might be the reason why it is not working. I'm wondering how to write the appropriate test as suggested.
Another Edit:
As a test, I commented out the password-encoder element and tried the authentication with a plain text password (i.e., I created a test user and stored a plain text password in the database). It worked. So, the problem is definitely with the way Spring Security is encoding the password entered by the user, which does not match the hashed password stored in the database.
Well, to solve my problem I implemented a custom password encoder. Basically, I overrode the matches method of the PasswordEncoder interface:
#Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
//encoding raw password: the given encodedPassword serves as the salt
String sql = "SELECT crypt(?, ?) as hashedpwd;";
String hashedPassword = aJdbcTemplate.query(sql, new String[] {rawPassword.toString(), encodedPassword}, new ResultSetExtractor<String>() {
#Override
public String extractData(ResultSet rs) throws SQLException, DataAccessException {
rs.next();
return rs.getString("hashedpwd");
}
});
return encodedPassword.equals(hashedPassword.toString());
}
It is ok to delete using GET if im using Spring MVC with Spring security? I can secure /entity/delete/{id} path to a group of users.
What do you mean "is it ok"? It will work, yes. It would be clearer to use the actual DELETE verb. You can use Spring's HiddenHttpMethodFilter to achieve this, while securing the URL with Spring Security using something like this:
<sec:intercept-url pattern="/entity/**" method="DELETE" access="hasRole('ROLE_ADMIN')" />
I'm making a Spring MVC web-app with some RESTfull resources as an API.
I need the RESTfull part to have some custom filters as I do not want any redirection and I want any exception to be translated with the corresponding HTTP error code and a basic JSON description.
On the other hand, the rest of the website have to be more common and redirect people when they are not logged in etc.
One more thing, I wish to use the #Secured annotations and a post-authentication in some case.
How do I define the multiple http namespaces correctly (on Spring 3.1)?
Here is my erroneous configuration:
<global-method-security secured-annotations="enabled" />
<http pattern="/rest/**" authentication-manager-ref="authenticationManager" entry-point-ref="restAuthenticationEntryPoint">
<form-login login-page="/rest/login" login-processing-url="/rest/postlogin"
authentication-success-handler-ref="restAuthenticationSuccessHandler"
authentication-failure-handler-ref="restAuthenticationFailureHandler"
username-parameter="username" password-parameter="password" />
<logout logout-url="/rest/logout" invalidate-session="true" />
</http>
<http pattern="/**" authentication-manager-ref="authenticationManager">
<form-login login-page="/login" login-processing-url="/postlogin"
username-parameter="username" password-parameter="password" />
<logout />
</http>
The funny part is that this configuration works partially as I can login with /rest/login and I get the response from my custom success handler. I can also login from /login and I get the proper redirection to /. The logout are working both fine too.
Next, all the controllers beans have #Secured("ROLE_USER") in the secured methods. But all the secured methods don't ever get secured. Why is that so?
#Secured({"ROLE_USER"})
#RequestMapping(method = RequestMethod.GET, headers = { "Range" })
public #ResponseBody
HttpEntity<List<T>> list(#RequestHeader("Range") String range) {
I've read documentations everywhere and I'm more confused than ever.
Why are my methods not being secured?
Must the http namespace define an access so that the #Secured annotations work?
Are the http namespace overwriting my #Secured annotations? If it's so, how can I define multiple "login pages" with custom filters and being able to use annotations?
Here are some facts:
* I'm using Spring and SpringSecurity 3.1
* I have a custom AuthenticationManager to retrieve user details from hibernate daos.
* Some controllers are extending an abstract class where the #Secured annotations lies. But it still doesn't work for a simple controller.
* My controllers are discovered with a context:component-scan and a base-package.
* The security works fine with one http namespace.
please help, i'm getting mad with this!
Check out this answer about making sure the web context is visible to the global-method-security declaration and possibly using class proxying.
To answer your other questions, no the http namespace shouldn't affect the use of #Secured annotations, other than that the user is authenticated by the web part of the application and that information will be used by the method security interceptor when making an access decision. Unless you override it (using access-decision-manager-ref), method security will use a standard AccessDecisionManager which grants or denies access based on the roles a user has.
I have a web application secured with spring security (Spring 3.1.0). Now if a customer wants to register to my service, Spring Security say "No". This makes sense because the user is not yet authorized.
The controller, which gets the register data is a spring mvc controller. I need to exclude this from spring security I think.
I've excluded some urls so far like this:
<intercept-url pattern="/index.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY" />
Is it possible, to exclude a (Spring MVC)Controller, or is this the wrong way to approach this?
By the way, I also tried to annotate tho at the method:
#PreAuthorize("hasRole('IS_AUTHENTICATED_ANONYMOUSLY')")
Why don't you try permitAll instead?
<intercept-url pattern="/index.jsp" access="permitAll" />