Spring Security : How to Authorize functions without log in - spring-security

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.

Related

How to set redirection after successful login?

I am using spring boot with the spring-boot-starter-security dependency.
I have an application that will successfully login given the proper credentials. However, whenever I login I am not being redirected anywhere. How can I configure this?
Below is the form:
<form th:action="#{/login}" method="post">
<div><label> User Name : <input type="text" name="username"/> </label></div>
<div><label> Password: <input type="password" name="password"/> </label></div>
<div><input type="submit" value="Sign In"/></div>
</form>
I have tried changing the th:action tag above but I wasn't able to get anywhere with it.
The MvcConfig method is below:
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
registry.addViewController("/").setViewName("login");
}
Defining the redirection after a successful login needs to be applied on Spring Security, not Spring MVC.
The th:action defines the Spring Security endpoint that will process the authentication request. It does not define the redirection URL. Out of the box, Spring Boot Security will provide you the /login endpoint. By default, Spring Security will redirect after login to the secured ressource you tried to access. If you wish to always redirect to a specific URL, you can force that through the HttpSecurity configuration object.
Assuming you are using a recent version of Spring Boot, you should be able to use JavaConfig.
Here is a simple exemple :
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserService userService;
#Override
protected void configure(HttpSecurity http) throws Exception {
// the boolean flags force the redirection even though
// the user requested a specific secured resource.
http.formLogin().defaultSuccessUrl("/success.html", true);
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService);
}
}
Please note that you need to define a proprer endpoint to serve content for the /success.html URL. A static resource available by default in src/main/resources/public/ would do the trick for test purpose. I would personnally rather define a secured URL served by a Spring MVC Controller serving content with Thymeleaf. You don't want any anonymous user to be able to access the success page. Thymeleaf as some usefull features to interact with Spring Security while rendering the HTML content.
Regards,
Daniel
It works for me. Once the login has been successful, Spring security redirects to "/" and then, I checks if the user is authenticated and in this case, redirects it to my dashboard page.
#RequestMapping("/")
public String index(Model model) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (!(auth instanceof AnonymousAuthenticationToken))
return "dashboard";
// if it is not authenticated, then go to the index...
// other things ...
return "index";
}
You can also define the post-login re-direction dynamically. It turns out to be crazy simple.
Suppose you have a controller that has complicated conditions where you need to ensure that the user is correctly logged in.
By setting a value in the "request" cache to the current request/response, and then doing a re-direct, Spring security will forward to the cached request after the login is successful.
RequestCache requestCache = new HttpSessionRequestCache();
requestCache.saveRequest(request,response);
return "redirect:/login";
No, this doesn't seem to be documented anywhere. The only reference to it I found was the following:
SavedRequests and the RequestCache Interface
Another responsibility of ExceptionTranslationFilter responsibilities is to save the current request before invoking the AuthenticationEntryPoint. This allows the request to be restored after the user has authenticated (see previous overview of web authentication). A typical example would be where the user logs in with a form, and is then redirected to the original URL by the default SavedRequestAwareAuthenticationSuccessHandler (see below).
The RequestCache encapsulates the functionality required for storing and retrieving HttpServletRequest instances. By default the HttpSessionRequestCache is used, which stores the request in the HttpSession. The RequestCacheFilter has the job of actually restoring the saved request from the cache when the user is redirected to the original URL.

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 - check if web url is secure / protected

Is there a way to "ask" spring security if the current request is secure? Because even if I am authenticated I want to detect if I am in a secure protected URL or in a anonymous / public page
Thanks in advance!
Spring Security provides JSP tag support for this. For example:
<sec:authorize url="/admin">
This content will only be visible to users who are authorized to access the "/admin" URL.
</sec:authorize>
Thymeleaf provides a Spring Security Dialect that has direct support for checking URL authorization with Spring Security. For example:
<div sec:authorize-url="/admin">
This will only be displayed if authenticated user can call the "/admin" URL.
</div>
If your technology does not support performing the check directly, you can easily use the WebInvocationPrivilegeEvaluator (this is the object that the JSP taglib and Thymeleaf use). For example, you can #Autowire an instance of WebInvocationPrivilegeEvaluator and use it directly. Obviously the syntax will vary depending on where you use it (i.e. GSP, Freemarker, etc), but here is an example in straight Java code.
#Autowired
WebInvocationPrivilegeEvaluator webPrivs;
public void useIt() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
boolean hasAdminAccess = webPrivs.isAllowed("/admin", authentication);
boolean hasAdminPostAccess = webPrivs.isAllowed(null, "/admin", "POST", authentication);
}
I think you can use your own implementation for AccessDecisionVoter then just simply override Vote method and compare intercept url using filterInvocation.getRequestUrl(); method.
#Override
public int vote(Authentication authentication, FilterInvocation filterInvocation,
Collection<ConfigAttribute> attributes) {
String requestUrl = filterInvocation.getRequestUrl();
....
}
We can mark it is as secure channel so converted to https:// url.
<intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" requires-channel="https" />
We can then use request.getScheme() to identify it.
I used org.springframework.security.version 3.1.4.RELEASE

Spring Security Authentication using MyBatis

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.

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