Spring Security Authentication using MyBatis - spring-security

I am trying to perform Spring Security Authentication using MyBatis.
My spring-security file looks as follows
<global-method-security pre-post-annotations="enabled" />
<beans:bean id="myUserService"
class="com.service.CustomService" />
<authentication-manager>
<authentication-provider user-service-ref="myUserService" />
</authentication-manager>
My CustomService class implements UserDetailsService and in the loadUserByUsername method , I am using my MyBatis Dao to load the Users from the DB.
#Autowired
private MyBatisDao dao;
In my Controller class I am using the same annotation , and in that case it returns the proper object.
But when I use the same in the CustomService class it returns null.
I am unable to understand the reason for it. Am i missing something. Please help
Any example of Spring Authentication using MyBatis would help, I can understand it and then maybe figure out the issue

I fix this issue by another - not recommended way.
In this case, #controller can treat the db work right,
so I do basic auth in controller and send that result to custom service.
Custom service has no valid auth function in this case.
If useename and password is valid, custom service is called,
and that just returns dummy auth result.
If username and password is invalid, i just didn't call the auth in controller.
Though it's not quite right way, it works fine with some special treat for user role.
I want to know there's a better way to solve this problem,
but i have no time to find, right now.

Issue solved by taking an alternative approach in constructing the MyBatis Object.
I created a singleton class which returns the SqlSessionFactory Object, and using the same in my code for calling the Mapper Interfaces methods.
Sample code snippet below
InputStream myBatisConfigStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("config.xml");
if (null == sqlSessionFactory){
sqlSessionFactory = new SqlSessionFactoryBuilder().build(myBatisConfigStream);
sqlSessionFactory.getConfiguration().addMapper(IOMapper.class);
}
try {
myBatisConfigStream.close();
} catch (IOException e) {
e.printStackTrace();
}
public static SqlSessionFactory getSqlSessionFactory() {
return sqlSessionFactory;
}
The config.xml file contains only the dataSource.
Hope this helps.

Related

Spring Security : How to Authorize functions without log in

I implemented spring security in my web application. Now all my services are secured and can be only invoked by authorised users. Everything works on webside, but when I call function without log in doesn't work.
here is my Controller(RestController)
#RestController
public class MessageService {
#Autowired
MessageModel messageModel;
#RequestMapping(value="/message",method=RequestMethod.POST)
public Message save(#RequestBody Message message) {
return messageModel.save(message);
}
#PreAuthorize("permitAll()")
#RequestMapping(value="/messagee",method=RequestMethod.POST)
public Message savee(#RequestBody Message message) {
System.out.println("hjgjhghggfhgf");
return messageModel.savee(message);
}
}
I am using angularjs client side.
The functions are not supposed to work as they are secured by spring security. To allow a few functions to be accessed anonymously, you need to configure spring security to do so.
Depending on what configuration you are using, I would suggest the below:
If you are using XML/Java route based config, I would recommend you to do something like this:
<security:intercept-url pattern="/trusted/**" filters="none" />
<security:intercept-url pattern="/**" access="isFullyAuthenticated()" />
If you are using the #PreAuthorize annotation, I would recommend you to do something like this:
#PreAuthorize("permitAll()")
public void YourAnonymousController(){
}
Hope this is what you are looking for.
EDIT 1: Please note that you remove the route based security config. Try adding #PreAuthorize("hasRole()") on functions you want to keep secured and #PreAuthorize("permitAll()") on anonymous functions.

UserManager VerifyUserTokenAsync Always False

I'm generating a usertoken like so
public async Task GenerateCode()
{
var code = await UserManager.GenerateUserTokenAsync("heymega", new Guid("16139fcd-7ae0-449c-ad1c-f568bbe46744"));
}
I then pass the same token into another action via a separate request
public async Task ValidateCode(string code)
{
var valid = await UserManager.VerifyUserTokenAsync(new Guid("16139fcd-7ae0-449c-ad1c-f568bbe46744"), "heymega", code); //Returns False
}
However, the response from the VerifyUserTokenAsync method is always false.
If I were to generate the code and verify within the same action
public async Task GenerateCode()
{
var code = await UserManager.GenerateUserTokenAsync("heymega", new Guid("16139fcd-7ae0-449c-ad1c-f568bbe46744"));
var valid = await UserManager.VerifyUserTokenAsync(new Guid("16139fcd-7ae0-449c-ad1c-f568bbe46744"), "heymega", code); //Returns True
}
It returns true.
Why can't the Verify method verify the code in a separate request? Am I missing something obvious?
I finally figured this after pulling my hair out for hours. You need to URL encode the code and I decided to use the HttpUtility class for this.
HttpUtility.UrlEncode(code);
When it comes to verifying the code, you do not need to URL decode the code.
Having just burned 2 days on this issue, here is another reason this might be happening to you.
In your Startup.cs - ConfigureServices(IServiceCollection services) method, ensure that:
services.AddAuthentication
Appears BEFORE
services.AddIdentity
Otherwise calls to VerifyUserTokenAsync will always return false
Cannot solve this problem until haven't used this:
UserManager.VerifyUserTokenAsync(userId, AccountLockedOutPurpose, code).WithCurrentCulture<bool>();
.WithCurrentCulture() - used in all methods such as ResetPasswordAsync etc.)
In my situation I was instantiating a UserManager on demand when one was needed, as opposed to generating one per Owin context in my startup pipeline. Behavior wise, if I validated the token with the same instance of UserManager that created it, it would return true. But if I did an actual forgot password flow where the validation is in a separate request, it was always false.
Switching my setup so that a UserManager was created per owin context resolved the issue for me. Apparently there is some dependency on Owin when it comes to validating tokens.
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
Not sure if OP is using .Net Core or not, but if someone comes across this and you're using dependency injection, the solution for me was to scope the UserManager as a singleton.
services.AddSingleton<UserManager<YourUserAccountModel>>();
I believe this is because when the user clicks the confirm email link in their inbox, a new UserManager instance is injected to the controller and does not have the same key that was used to generate the token to begin with. Therefore it cannot verify the token.
For me, I got the same issue. and the solution was very simple.
In my case, I add the purpose with white space like this "Email Confirmation".
the problem was solved when I removed any white space "EmailConfirmation".
bool IsTokenValed = await userManager.VerifyUserTokenAsync(user, userManager.Options.Tokens.EmailConfirmationTokenProvider, "EmailConfirmation", token);

Does AOP with AspectJ works with method from Managed Bean called from the view in JSF2?

I’m currently facing a Problem using a combination of JSF 2 and AOP with AspectJ annotation.
I don't know if Spring AOP is playing a role here...(I didn't well understand difference between SPRING AOP, ASPECTJ, GOOGLE GUICE...that's an another question)
I'm trying to send an e-mail after i added some values in my database via click on a form in jsf view.
I have a managedBean AddPartipant handled by JSF (linked to a view) to add participant via a form. I want to intercept the method who makes the change in database and send an email just after this action.
I have a spring bean SendMailBoImpl with a method to send an email.(sending works ok)
I found using a AOP was a good way. It's works only when i trying to make it works in a main...not in the complete webapp. I read some stuffs about problem context spring / Jsf but don't found a solution...yet...
I know my method to add data in the database via the view is ok...but the mail is never sent whereas the database is modified.
Somebody has an idea ?
Thanks a lot :)
AddParticipant ManagedBean :
public class AddParticipant implements Serializable{
//DI via Spring
ParticipantBo participantBo;
private String id_study ;
private Participant aParticipant = new Participant();
//getters and setters
public void addParticipant(){
aParticipant.setId_study (id_study);
...
participantBo.save(aParticipant);
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Ajout du participant "+id_study+" dans l'étude "+ study_name));
}
MaiBo Service :
#After("execution(* com.clb.genomic.lyon.beans.AddParticipant.addParticipant(..))")
public void sendMail() {
....
mailSender.send(message);
....
}
My bean config :
<aop:aspectj-autoproxy proxy-target-class="true" />
<bean id="addParticipant" class="com.clb.genomic.lyon.beans.AddParticipant"/>
<bean id="sendMailBo" class="com.clb.genomic.lyon.bo.SendMailBoImpl">
<property name="mailSender" ref="mailSender" />
<property name="simpleMailMessage" ref="customeMailMessage" />
</bean>
When i do this it's working :
ApplicationContext appContext = new ClassPathXmlApplicationContext
( "classpath:webConfiguration/applicationContext.xml");
AddParticipant aspect = (AddParticipant) appContext.getBean("addParticipant");
aspect.addParticipant();
Solved base on the read of this : http://kumarnvm.blogspot.fr/2012/07/using-spring-to-manage-jsf-september-10_14.html

Return username and password to login form grails spring security

When a user fails authentication, I want the username and password to be returned to the form.
I'm using the spring security core plugin with Grails and Spring Security LDAP. I've searched around for a while and have come up with zip. Any ideas?
From UsernamePasswordAuthenticationFilter javadoc:
If you want to retain the username, cache it in a customized AuthenticationFailureHandler
As for password there is no point to cache it, because it cannot be put back to form password field for security reasons.
For future reference, as the above answers are either too vague to be helpful to those of us who are just beginning to learn this framework for the first time (prompting such questions as: what's an AuthenticationFailureHandler? How do I implement one? How do I connect it to my existing infrastructure that was magically created by the <security:http> namespace handler?) or no longer work (the code to store the username in SPRING_SECURITY_LAST_USERNAME was removed from UsernamePasswordAuthenticationFilter as of version 3.1.0), here's a little more detail on the first answer:
An AuthenticationFailureHandler is used by the login process to decide what to do when authentication fails.
The default login form setup as provided by <security:http><security:form-login /></security:http> uses a SimpleUrlAuthenticationFailureHandler to perform the redirection to the login failed url (which defaults to /spring_security_login?login_error).
You can hook your own implementation in by using the authentication-failure-handler-ref attribute of your <form-login> element.
So, my implementation looks like this:
public class UsernameStoringUrlAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler
{
#Override
public void onAuthenticationFailure (HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException
{
request.getSession (true).setAttribute ("SPRING_SECURITY_LAST_USERNAME", request.getParameter ("j_username"));
super.onAuthenticationFailure (request, response, exception);
}
}
which is configured thus:
<security:form-login authentication-failure-handler-ref="authenticationFailureHandler" [...] />
...
<bean id="authenticationFailureHandler" class="my.package.UsernameStoringUrlAuthenticationFailureHandler" p:defaultFailureUrl="/LoginError" />
And then I can access the failed login username using the same approach as described in James Kleeh's answer here, but which no longer worked because of the change to the framework.
I was able to do the following to get the username back to the form: In LoginController.groovy:
render view: view, model: [postUrl: postUrl,
rememberMeParameter: config.rememberMe.parameter,
lastUsername: request.getSession().getAttribute("SPRING_SECURITY_LAST_USERNAME")]

Spring Security 3: Method Level Access Failure

I have url-level security in placed, and also, method level. But my method level security is bypassed once the user has been authenticated at the url-level! I looked at this further and it seems that the following url-level security:
intercept-url pattern="/**" access="ROLE_USER"
would override any of my method level security (like below code snippet).
#PreAuthorize("hasRole('ROLE_SUPERVISOR')")
public String supervisorRoleOnly()
{
return "success!!!" ;
}
I would think that this method would throw an access-denied error, but no, any ROLE_USER can access this method once they are already authenticated at the url-level.
I do have this in my security-config.xml:
<global-method-security pre-post-annotations="enabled" >
<expression-handler ref="expressionHandler"/>
</global-method-security>
What am I missing?
I guess this applies more to future readers, but when you set debug logging for Spring Security do you see something similar to following:
Looking for Pre/Post annotations for method 'supervisorRoleOnly' on target class 'yourClassName'
No expression annotations found
Adding security method [CacheKey[yourClassName; public yourReturnType yourClassName.supervisorRoleOnly()]] with attributes [ROLE_USER]
PreAuthorize is probably being ignored.

Resources