Friday, February 19, 2016

Spring Security



http://docs.spring.io/spring-security/site/docs/4.1.x/guides/html5/hellomvc-javaconfig.html
public class MessageSecurityWebApplicationInitializer
      extends AbstractSecurityWebApplicationInitializer {
}


The MessageSecurityWebApplicationInitializer will automatically register the springSecurityFilterChain Filter for every URL in your application. If Filters are added within other WebApplicationInitializer instances we can use@Order to control the ordering of the Filter instances.
http://stackoverflow.com/questions/24122586/how-to-represent-the-spring-security-custom-filter-using-java-configuration
  1. Your filter needs to be added before the standard UsernamePasswordAuthenticationFilter
    
    http.addFilterBefore(customUsernamePasswordAuthenticationFilter(),
            UsernamePasswordAuthenticationFilter.class)
  2. If you extend UsernamePasswordAuthenticationFilter your filter will return immediately without doing anything unless you set a RequestMatcher
    
    myAuthFilter.setRequiresAuthenticationRequestMatcher(
        new AntPathRequestMatcher("/login","POST"));
  3. All the configuration you do in http.formLogin().x().y().z() is applied to the standard UsernamePasswordAuthenticationFilter not the custom filter you build. You will need to configure it manually yourself. My auth filter initialization looks like this:
    
    @Bean
    public MyAuthenticationFilter authenticationFilter() {
        MyAuthenticationFilter authFilter = new MyAuthenticationFilter();
        authFilter.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/login","POST"));
        authFilter.setAuthenticationManager(authenticationManager);
        authFilter.setAuthenticationSuccessHandler(new MySuccessHandler("/app"));
        authFilter.setAuthenticationFailureHandler(new MyFailureHandler("/login?error=1"));
        authFilter.setUsernameParameter("username");
        authFilter.setPasswordParameter("password");
        return authFilter;
    }
http://www.baeldung.com/spring-security-session
Before executing the Authentication process, Spring Security will run a filter responsible with storing the Security Context between requests – the SecurityContextPersistenceFilter. The context will be stored according to a strategy – HttpSessionSecurityContextRepository by default – which uses the HTTP Session as storage.
For the strict create-session=”stateless” attribute, this strategy will be replaced with another –NullSecurityContextRepository – and no session will be created or used to keep the context.
4. Concurrent Session Control
When a user that is already authenticated tries to authenticate again, the application can deal with that event in one of a few ways. It can either invalidate the active session of the user and authenticate the user again with a new session, or allow both sessions to exist concurrently.
http.sessionManagement().maximumSessions(2)
http.sessionManagement()
    .expiredUrl("/sessionExpired.html")
    .invalidSessionUrl("/invalidSession.html");
Exposing session information in the URL is a growing security risk (from place 7 in 2007 to place 2 in 2013 on the OWASP Top 10 List).
Starting with Spring 3.0, the URL rewriting logic that would append the jsessionid to the URL can now be disabled by setting the disable-url-rewriting=”true” in the <http> namespace.
Alternatively, starting with Servlet 3.0, the session tracking mechanism can also be configured in the web.xml:
1
2
3
<session-config>
     <tracking-mode>COOKIE</tracking-mode>
</session-config>
And programmatically:
1
servletContext.setSessionTrackingModes(EnumSet.of(SessionTrackingMode.COOKIE));
This chooses where to store the JSESSIONID – in the cookie or in a URL parameter.
http.sessionManagement()
    .sessionFixation().migrateSession()
By default, Spring Security has this protection enabled (“migrateSession“) – on authentication a new HTTP Session is created, the old one is invalidated and the attributes from the old session are copied over.
If this is not the desired behaviour, two other options are available:
  • when “none” is set, the original session will not be invalidated
  • when “newSession” is set, a clean session will be created without any of the attributes from the old session being copied over


http://stackoverflow.com/questions/15946132/springsecurity-fail-to-delete-jsessionid
.addLogoutHandler(new ProperCookieClearingLogoutHandler("JSESSIONID","USER"))
The default CookieClearingLogoutHandler provided by spring could not clear JSESSIONID due to a difference in cookie path.
You should not change the path of cookie. This would change the cookie identity. If the cookie were set for a path like /foo and you change this to /, then the client won't associate the changed cookie with the original cookie anymore. A cookie is identified by the name and the path.
Therefore you need to implement a custom CookieClearingLogoutHandler as shown in the above solution i.e (ProperCookieClearingLogoutHandler.class) and set it to spring security as shown in below code .Instead of using .deleteCookies("JSESSIONID","USER") which adds CookieClearingLogoutHandler by default.
public final class ProperCookieClearingLogoutHandler implements LogoutHandler {
    private final List<String> cookiesToClear;

    public ProperCookieClearingLogoutHandler(String... cookiesToClear) {
        Assert.notNull(cookiesToClear, "List of cookies cannot be null");
        this.cookiesToClear = Arrays.asList(cookiesToClear);
    }

    public void logout(HttpServletRequest request, HttpServletResponse response,
            Authentication authentication) {
        for (String cookieName : cookiesToClear) {
            Cookie cookie = new Cookie(cookieName, null);
            String cookiePath = request.getContextPath() + "/";
            if (!StringUtils.hasLength(cookiePath)) {
                cookiePath = "/";
            }
            cookie.setPath(cookiePath);
            cookie.setMaxAge(0);
            response.addCookie(cookie);
        }
    }
}
https://java.net/jira/browse/JERSEY-2919
http://stackoverflow.com/questions/21586070/spring-security-preauthorize-breaks-jersey-context-uriinfo-injection
Actually a workaround seems to be to inject the @Context UriInfo uriInfo into the resource method instead of at the class level.

http://stackoverflow.com/questions/33541678/preauthorizepermitall-still-requires-authentication
Method security is applied after the web security filter.
Since you have anyRequest().fullyAuthenticated() in your configuration, your findAll method will never be hit. anyRequest().fullyAuthenticated() means that all attempts to access a web endpoint that does no have have some from of full user authentication on it will fail.
From the JavaDoc
Specify that URLs are allowed by users who have authenticated and were not "remembered".
You will need to add an additional path in your web security, some like.
protected void configure(final HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .anyRequest().fullyAuthenticated()
            .antMatchers(HttpMethod.GET, '/somePath').permitAll()
         .and()
            .httpBasic()
         .and()
            .csrf().disable();
}
http://www.baeldung.com/spring-security-logout
<logout
    logout-url="/perform_logout"
    delete-cookies="JSESSIONID"
    success-handler-ref="customLogoutSuccessHandler" />

http://websystique.com/spring-security/spring-security-4-method-security-using-preauthorize-postauthorize-secured-el/
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
  • prePostEnabled :Determines if Spring Security’s pre post annotations [@PreAuthorize,@PostAuthorize,..] should be enabled.
  • secureEnabled : Determines if Spring Security’s secured annotation [@Secured] should be enabled.
  • jsr250Enabled : Determines if JSR-250 annotations [@RolesAllowed..] should be enabled.
You can enable more than one type of annotation in the same application, but only one type should be used for any interface or class as the behavior will not be well-defined otherwise. If two annotations are found which apply to a particular method, then only one of them will be applied.
@Secured annotation is used to define a list of security configuration attributes for business methods. You can specify the security requirements[roles/permission etc] on a method using @Secured, and than only the user with those roles/permissions can invoke that method. If anyone tries to invoke a method and does not possess the required roles/permissions, an AccessDenied exception will be thrown.
@Secured is coming from previous versions of Spring. It has a limitation that it does not support Spring EL expressions.
Spring’s @PreAuthorize/@PostAuthorize annotations are preferred way for applying method-level security, and supports Spring Expression Language out of the box, and provide expression-based access control.
@PreAuthorize is suitable for verifying authorization before entering into method. @PreAuthorize can take into account, the roles/permissions of logged-in User, argument passed to the method etc.
@PostAuthorize , not often used though, checks for authorization after method have been executed, so it is suitable for verifying authorization on returned values. Spring EL provides returnObject object that can be accessed in expression language and reflects the actual object returned from method.
    @PostAuthorize ("returnObject.type == authentication.name")
    User findById(int id);
    @PreAuthorize("hasRole('ADMIN')")
    void updateUser(User user);
     
    @PreAuthorize("hasRole('ADMIN') AND hasRole('DBA')")
    void deleteUser(int id);
Additionally, we have added a method findById() with @PostAuthorize annotation. With @PostAuthorize, the returned value from the method(User object) will be accessible with returnObject in Spring Expression Language, and individual properties of return user object can be used to apply some security rules. In this example we are making sure that a logged-in user can only get it’s own User type object.
http://docs.spring.io/spring-security/site/docs/3.0.x/reference/el-access.html

Filtering using @PreFilter and @PostFilter

As you may already be aware, Spring Security supports filtering of collections and arrays and this can now be achieved using expressions. This is most commonly performed on the return value of a method. For example:
  @PreAuthorize("hasRole('ROLE_USER')")
  @PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, 'admin')")
  public List<Contact> getAll();
When using the @PostFilter annotation, Spring Security iterates through the returned collection and removes any elements for which the supplied expression is false. The name filterObject refers to the current object in the collection. You can also filter before the method call, using @PreFilter, though this is a less common requirement. The syntax is just the same, but if there is more than one argument which is a collection type then you have to select one by name using thefilterTarget property of this annotation.


       
      http.authorizeRequests()
        .antMatchers("/", "/home").access("hasRole('USER') or hasRole('ADMIN') or hasRole('DBA')")
        .and().formLogin().loginPage("/login")
        .usernameParameter("ssoId").passwordParameter("password")
        .and().exceptionHandling().accessDeniedPage("/Access_Denied");
    }
http://stackoverflow.com/questions/27390363/spring-how-to-inject-an-inline-list-of-strings-using-value-annotation
The spring convertion service will perform the split for you if your reference is an array or Collection, so you don't need that ugly expression: just @Value("${list.of.strings}")

http://stackoverflow.com/questions/16113115/how-do-i-use-a-custom-authorities-populator-with-spring-security-and-the-actived

http://forum.spring.io/forum/spring-projects/security/101786-spring-security-how-to-add-remove-authorities-of-the-user-after-he-logs-in
The easiest option is to obtain the current Authentication and create a new instance of it and set it on the SecurityContextHolder as described in Setting the SecurityContextHolder Contents Directly. Be sure you understand the implications of acting upon the Authentication in multiple threads (read on in the reference to understand). An example of adding a GrantedAuthority to the current Authentication is given below:

Code:
// update database with new role
//... you fill in this part

// update the current Authentication
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(auth.getAuthorities());
authorities.add(new GrantedAuthorityImpl('ROLE_NEWROLE'));
Authentication newAuth = new UsernamePasswordToken(auth.getPrincipal(),auth.getCredentials(),authorities)
SecurityContextHolder.getContext().setAuthentication(newAuth);

https://spapas.github.io/2013/10/14/spring-ldap-custom-authorities/
@Component
public class CustomLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator {
       @Override
       public Collection<? extends GrantedAuthority> getGrantedAuthorities(
                       DirContextOperations userData, String username) {
               Collection<GrantedAuthority> gas = new HashSet<GrantedAuthority>();
               if(username.equals("spapas")) {
                       gas.add(new SimpleGrantedAuthority("admin"));
               }
               gas.add(new SimpleGrantedAuthority("user"));
               return gas;
       }
}
http://stackoverflow.com/questions/25398301/manually-authenticate-use-spring-security

http://stackoverflow.com/questions/22845474/spring-security-3-2-1-multiple-login-forms-with-distinct-websecurityconfigurerad
The component of the spring login chain that redirects to a login page is the authentication filter, and the filter that get's plugged in when using http.formLogin() is DefaultLoginPageGeneratingFilter.
This filter either redirects to the login url or builds a default basic login page, if no login page url is provided.
What you need then is a custom authentication filter with the logic to define which login page is needed, and then plug it in the spring security chain in place of the single page authentication filter.

http://stackoverflow.com/questions/25794680/multiple-authentication-mechanisms-in-a-single-app-using-java-config

http://docs.spring.io/spring-security/site/docs/current/reference/html/jc.html
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

 @Autowired
 public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
  auth
   .inMemoryAuthentication()
    .withUser("user").password("password").roles("USER");
 }
}

The name of the configureGlobal method is not important. However, it is important to only configure AuthenticationManagerBuilder in a class annotated with either @EnableWebSecurity@EnableGlobalMethodSecurity, or @EnableGlobalAuthentication. Doing otherwise has unpredictable results.

public class SpringWebMvcInitializer extends
   AbstractAnnotationConfigDispatcherServletInitializer {

  @Override
  protected Class<?>[] getRootConfigClasses() {
    return new Class[] { HelloWebSecurityConfiguration.class };
  }
  ...
}
http://stackoverflow.com/questions/30536938/how-to-implement-spring-security-4-with-both-xml-and-java-config
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
  auth.inMemoryAuthentication().withUser("abc").password("123456").roles("USER");
  auth.inMemoryAuthentication().withUser("admin").password("123456").roles("ADMIN");
  auth.inMemoryAuthentication().withUser("dba").password("123456").roles("DBA");
}

@Override
protected void configure(HttpSecurity http) throws Exception {

  http.authorizeRequests()
    .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
    .antMatchers("/dba/**").access("hasRole('ROLE_ADMIN') or hasRole('ROLE_DBA')")
    .and().formLogin();

    }
}
http://stackoverflow.com/questions/7413304/favicon-ico-not-found-error
The issue is, when the browser cache is empty and a user comes in, here is what happens:
  • the user requests URL "/". This URL is cached.
  • the browser makes a requests to "/favicon.ico". This URL becomes the new URL where to redirect to upon authentication.
  • the user posts the login form and is redirected to "/favicon.ico".
To fix this, you need to set "/favicon.ico" as being a non-secured resources:
<intercept-url pattern="/favicon.ico" access="ROLE_ANONYMOUS" />
/favicon.ico is something which every browser tries to get from any site it visits to display a nice icon in the location bar. My first guess is that your application sends a login-form back to the browser instead of the file or a 404 NOT FOUND.
Get current logged in username in Spring Security
      Authentication auth = SecurityContextHolder.getContext().getAuthentication();
      String name = auth.getName(); //get logged in username

Spring security:





@EnableWebSecurity
@Configuration
public class CustomWebSecurityConfigurerAdapter extends
   WebSecurityConfigurerAdapter {
  @Autowired
  public void configureGlobal(AuthenticationManagerBuilder auth) {
    auth
      .inMemoryAuthentication()
        .withUser("user")  // #1
          .password("password")
          .roles("USER")
          .and()
        .withUser("admin") // #2
          .password("password")
          .roles("ADMIN","USER");
  }

  @Override
  public void configure(WebSecurity web) throws Exception {
    web
      .ignoring()
         .antMatchers("/resources/**"); // #3
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
      .authorizeUrls()
        .antMatchers("/signup","/about").permitAll() // #4
        .antMatchers("/admin/**").hasRole("ADMIN") // #6
        .anyRequest().authenticated() // 7
        .and()
    .formLogin()  // #8
        .loginUrl("/login") // #9
        .permitAll(); // #5
  }
}

http://stackoverflow.com/questions/23344787/spring-ldap-security-without-xml
I've modified SecurityConfig.java as follows:
    public void registerGlobalAuthentication(AuthenticationManagerBuilder auth) throws Exception {
        DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(ldap_url);
        contextSource.setUrl(ldap_user);
        contextSource.setPassword(ldap_password);

        DefaultLdapAuthoritiesPopulator ldapAuthoritiesPopulator = new DefaultLdapAuthoritiesPopulator(contextSource, "ou=groups");
        ldapAuthoritiesPopulator.setGroupRoleAttribute("ou");

        LdapAuthenticationProviderConfigurer<AuthenticationManagerBuilder> ldapAuthenticationProviderConfigurer = auth.ldapAuthentication();

        ldapAuthenticationProviderConfigurer
            .userDnPatterns("uid={0},ou=people")
            .groupSearchBase("ou=groups")
            .contextSource(contextSource)
            .ldapAuthoritiesPopulator(ldapAuthoritiesPopulator);
    }
}
but when I login using the web form, I get this error:
java.lang.NullPointerException
    at java.util.Hashtable.<init>(Hashtable.java:296)
    at org.springframework.ldap.core.support.AbstractContextSource.getAuthenticatedEnv(AbstractContextSource.java:499)
    at org.springframework.ldap.core.support.AbstractContextSource.doGetContext(AbstractContextSource.java:114)
    at org.springframework.ldap.core.support.AbstractContextSource.getContext(AbstractContextSource.java:110)
    at org.springframework.security.ldap.authentication.BindAuthenticator.bindWithDn(BindAuthenticator.java:112)

You need to call
contextSource.afterPropertiesSet()
if you are using the class outside an application context (see the source and Javadoc for Spring LDAP's AbstractContextSource for more information). Either that or you can just make it an @Beanand Spring will call the method and initialize it for you.

Labels

Review (572) System Design (334) System Design - Review (198) Java (189) Coding (75) Interview-System Design (65) Interview (63) Book Notes (59) Coding - Review (59) to-do (45) Linux (43) Knowledge (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (31) Big Data (29) Product Architecture (28) MultiThread (27) Soft Skills (27) Concurrency (26) Cracking Code Interview (26) Miscs (25) Distributed (24) OOD Design (24) Google (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) System Design - Practice (20) Tips (19) Algorithm (17) Company - Facebook (17) Security (17) How to Ace Interview (16) Brain Teaser (14) Linux - Shell (14) Redis (14) Testing (14) Tools (14) Code Quality (13) Search (13) Spark (13) Spring (13) Company - LinkedIn (12) How to (12) Interview-Database (12) Interview-Operating System (12) Solr (12) Architecture Principles (11) Resource (10) Amazon (9) Cache (9) Git (9) Interview - MultiThread (9) Scalability (9) Trouble Shooting (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Cassandra (8) Company - Uber (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Design (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Mac (7) Machine Learning (7) NoSQL (7) C++ (6) Chrome (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) Python (5)

Popular Posts