I am new to configuring Spring Security using Java Config. I was trying to follow this posting. However, when I run my app, I get a Basic Auth challenge on all URLs, including /. Entering the either of the userid/pass combos below do not seem to work.
My Controller:
package com.xxx.web;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
#RequestMapping("/")
/**
* Controller to handle basic "root" URLs
*
* #author xxx
* #version 0.1.0
*/
public class RootController {
/**
* Handles '/'
* #param model
* #return
*/
#RequestMapping
public String index(Model model) {
return "index";
}
/**
* Handles '/signup'
* #param model
* #return
*/
#RequestMapping("/signup")
public String signup(Model model) {
return "signup";
}
/**
* Handles '/about'
* #param model
* #return
*/
#RequestMapping("/about")
public String about(Model model) {
return "about";
}
/**
* Handles '/login'
* #param model
* #return
*/
#RequestMapping("/login")
public String login(Model model) {
return "login";
}
/**
* Handles '/admin'
* #param model
* #return
*/
#RequestMapping("/admin")
public String admin(Model model) {
return "admin";
}
}
Not sure what else to try. Just looking for some guidance as to why this isn't working.
Update
For completeness, here is the config class:
package com.xxx.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#Configuration
#EnableWebSecurity
/**
* Configures the security for the application
*
* #author XXX
* #version 0.1.0
*
*/
public class WebSecurityAppConfig extends WebSecurityConfigurerAdapter {
#Override
/**
* #see org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter#registerAuthentication(AuthenticationManagerBuilder)
*/
protected void registerAuthentication(AuthenticationManagerBuilder auth)
throws Exception {
auth
.inMemoryAuthentication()
.withUser("user") // #1
.password("password")
.roles("USER")
.and()
.withUser("admin") // #2
.password("password")
.roles("ADMIN","USER");
}
#Override
/**
* #see org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter#configure(WebSecurity)
*/
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**"); // #3
}
#Override
/**
* #see org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter#configure(HttpSecurity)
*/
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/","/signup","/about").permitAll() // #4
.antMatchers("/admin/**").hasRole("ADMIN") // #6
.anyRequest().authenticated() // 7
.and()
.formLogin() // #8
.loginPage("/login") // #9
.permitAll(); // #5
}
}
And the WebApplicationInitializer:
package com.xxx.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
/**
*
* #author XXX
* #version 0.1.0
*/
public class SpringWebMvcInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
#Override
/**
*
*/
protected Class<?>[] getRootConfigClasses() {
return new Class[] { WebSecurityAppConfig.class };
}
#Override
/**
*
*/
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
/**
*
*/
protected String[] getServletMappings() {
return null;
}
}
I didn't include these before because they are pretty much a copy-paste from the referenced blog posting.
The original question is probably best answered by just describing the options available. Some applications (services that only need basic HTTP authentication) can use the default settings in the actuator, others will need to specify security.* properties (see SecurityProperties for options) and/or an AuthenticationManager (for user account details). The next level of control comes from adding your own WebSecurityConfigurerAdapter, and you can see how to do that by looking at the "secure" sample in Spring Boot.
Related
The following line doesn't let me visit GET: /api/topics without a bearer token. It works if I apply a token. Am I missing something? Isn't permitAll supposed to do that?
.antMatchers("/api/topics/**").permitAll()
By the way, I tried with /api/topics** and it didn't work as well.
Error:
{
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource"
}
Result without a token (the broken part). I want it to let me through.
Result with a token. It works as intended:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(jsr250Enabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/api/topics/**").permitAll()
.antMatchers("/api/users/**").permitAll()
.anyRequest().authenticated();
}
#Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}
#RestController
#RequestMapping("/api/topics")
public class TopicController {
#Autowired
private TopicService topicService;
#Autowired
private UserService userService;
#Autowired
private TopicMapper topicMapper;
/**
* Gets all topics.
*
* #return the topics.
*/
#GetMapping
public ResponseEntity<List<TopicDTO>> getAll() {
return ResponseEntity.ok(topicMapper.toTopicDTOs(topicService.getAll()));
}
/**
* Gets topic by id.
*
* #param id the id.
* #return the topic.
*/
#GetMapping("/{id}")
public ResponseEntity<TopicDTO> get(#PathVariable("id") Long id) {
Optional<TopicEntity> topicEntity = topicService.get(id);
return topicEntity.map(entity -> ResponseEntity.ok(topicMapper.toTopicDTO(entity))).orElseGet(() -> ResponseEntity.notFound().build());
}
/**
* Creates a new topic.
*
* #param topicDTO the topic DTO.
* #return the new topic DTO.
*/
#PostMapping
public ResponseEntity<TopicDTO> create(#RequestBody TopicDTO topicDTO) {
UserEntity userEntity = userService.get(topicDTO.getUserId()).orElseThrow(() -> new IllegalArgumentException("User does not exist."));
TopicEntity topicEntity = topicMapper.toTopicEntity(topicDTO);
topicEntity.setId(null);
topicEntity.setUser(userEntity);
Optional<TopicEntity> createdTopicEntity = topicService.create(topicEntity);
return createdTopicEntity.map(entity -> ResponseEntity.ok(topicMapper.toTopicDTO(entity))).orElseGet(() -> ResponseEntity.status(HttpStatus.CONFLICT).build());
}
/**
* Updates an existing topic.
* #param id the topic id.
* #param topicDTO the topic DTO.
* #return the updated topic DTO.
*/
#PutMapping("/{id}")
public ResponseEntity<TopicDTO> update(#PathVariable("id") Long id, #RequestBody TopicDTO topicDTO) {
UserEntity userEntity = userService.get(topicDTO.getUserId()).orElseThrow(() -> new IllegalArgumentException("User does not exist."));
TopicEntity topicEntity = topicMapper.toTopicEntity(topicDTO);
topicEntity.setId(id);
topicEntity.setUser(userEntity);
Optional<TopicEntity> updatedTopicEntity = topicService.update(topicEntity);
return updatedTopicEntity.map(entity -> ResponseEntity.ok(topicMapper.toTopicDTO(entity))).orElseGet(() -> ResponseEntity.badRequest().build());
}
/**
* Deletes an existing topic.
* #param id the topic id.
* #return the status code.
*/
#DeleteMapping("/{id}")
public ResponseEntity<Void> delete(#PathVariable("id") Long id) {
if (topicService.get(id).isPresent()) {
topicService.delete(id);
return ResponseEntity.ok().build();
}
return ResponseEntity.notFound().build();
}
}
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
#Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
#Autowired
private TokenStore tokenStore;
#Autowired
private AuthenticationManager authenticationManager;
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("trusted")
.secret(bCryptPasswordEncoder.encode("secret"))
.authorizedGrantTypes("password", "get_token", "refresh_token")
.scopes("read", "write")
.autoApprove(true)
.accessTokenValiditySeconds(15 * 60)
.refreshTokenValiditySeconds(30 * 60);
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.authenticationManager(authenticationManager)
.tokenStore(tokenStore);
}
#Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
}
#Configuration
#EnableResourceServer
public class ResourceServerConfiguration {
}
Because #EnableResourceServer will add its filter chain at order=3 by default.As for WebSecurityConfigurerAdapter implementation, adds its own filterchain at the order=100, as a result, request first goes through filter chain of set by #EnableResourceServer where everything is protected unless you provide token and that's why you are getting that behavior. Try to add order bellow 3 like #Order(2) annotation to your WebSecurityConfigurerAdapter implementation.
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(jsr250Enabled = true)
#Order(2) <<--- add this
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
...
}
For more information read: Changing the Filter Order
There is a mistake with URL patterns in antMatchers.
By default the pattern like /api/topics/** doesn't match /api/topics.
It matches only /api/topics/ and after slash can be zero or more symbols
For fixing this case can be several solutions:
Change the pattern in existing antMatchers to next /api/topics**
Use mvcMatchers instead of antMatchers. mvcMatchers("/api/topics").permitAll()
mvcMatchers - will use the same rules that Spring MVC uses for
matching. For example, often times a mapping of the path "/path" will
match on "/path", "/path/", "/path.html", etc.
More information about antMatchers can be found here
More information about mvcMatchers can be found here
I am not getting my head around why an AJAX-POST is not working on a dynamic web project which I created. I have got a servlet which I am able to call with its url, but whenever I make an AJAX-call to it, the request in the doPost-function is empty.
I thought that the URL in the AJAX call was wrong, but none of the URLs I tried could fix the problem. I know that the doPost-function in the servlet is called when I debugged it.
The servlet looks like this:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.mavenproject.mave;
import java.io.BufferedWriter;
import java.io.*;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.persistence.*;
import java.util.*;
/**
*
* #author andfe
*/
public class DB extends HttpServlet {
/**
* Processes requests for both HTTP <code>GET</code> and <code>POST</code>
* methods.
*
* #param request servlet request
* #param response servlet response
* #throws ServletException if a servlet-specific error occurs
* #throws IOException if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = response.getWriter()) {
/* TODO output your page here. You may use following sample code. */
out.println("<!DOCTYPE html>");
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet DB</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Servlet DB at " + request.getContextPath() + "</h1>");
out.println("</body>");
out.println("</html>");
}
}
// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
/**
* Handles the HTTP <code>GET</code> method.
*
* #param request servlet request
* #param response servlet response
* #throws ServletException if a servlet-specific error occurs
* #throws IOException if an I/O error occurs
*/
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Handles the HTTP <code>POST</code> method.
*
* #param request servlet request
* #param response servlet response
* #throws ServletException if a servlet-specific error occurs
* #throws IOException if an I/O error occurs
*/
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
write(request);
}
/**
* Returns a short description of the servlet.
*
* #return a String containing servlet description
*/
#Override
public String getServletInfo() {
return "Short description";
}// </editor-fold>
private void write(HttpServletRequest request) {
try (FileWriter writer = new FileWriter("C:\\Users\\andfe\\Desktop\\log.txt");
BufferedWriter bw = new BufferedWriter(writer)) {
bw.write(request.getContextPath());
} catch (IOException e) {
e.printStackTrace();
}
}
}
Here is my JavaScript:
/**
* This class is the controller for the main view for the application. It is specified as
* the "controller" of the Main view class.
*
* TODO - Replace this content of this view to suite the needs of your application.
*/
Ext.define('app.view.main.MainController', {
extend: 'Ext.app.ViewController',
alias: 'controller.main',
onItemSelected: function (sender, record) {
Ext.Msg.confirm('Confirm', 'Are you sure?', 'onConfirm', this);
},
onConfirm: function (choice) {
if (choice === 'yes') {
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "/mave/DB", true);
xhttp.setRequestHeader("Content-type", "Content-Type: text/html; charset=utf-8");
xhttp.send("test");
}
}
});
Change to:
xhttp.setRequestHeader("Content-type", "text/html; charset=utf-8");
I am trying to use Hazelcast Distributed Cache for replication of HTTP session with Spring Boot & Spring Security but unable to set this up (however, simple cache replication is working fine, I have verified this by setting some value in map on one application node and trying to get it on other cluster node).
I have gone through the stuff available over web but unfortunately I am unable to set this up. Application when runs in a cluster, after logging on one node, I do not get session object on other node (I am fetching session from session registry object).
I have included dependencies : hazelcast version: '3.12' and hazelcast-all version: '3.12'
in gradle build file.
Below is the code configurations I have tried so far.
I have added below bean in AppConfig.java
#Bean
public Config hazelCastConfig(){
Config config = new Config();
config.setInstanceName("hazelcast-instance")
.addMapConfig(
new MapConfig()
.setName("hazelcastConfiguration")
.setMaxSizeConfig(new MaxSizeConfig(200, MaxSizeConfig.MaxSizePolicy.FREE_HEAP_SIZE))
.setEvictionPolicy(EvictionPolicy.LRU)
.setTimeToLiveSeconds(-1));
NetworkConfig networkConfig = config.getNetworkConfig();
networkConfig.setPort(6701).setPortCount(20);
networkConfig.setPortAutoIncrement(true);
JoinConfig join = networkConfig.getJoin();
join.getMulticastConfig().setEnabled(false);
join.getTcpIpConfig()
.addMember("localhost")
.setEnabled(true);
return config;
}
#Bean
public FilterRegistrationBean hazelcastFilter(HazelcastInstance hazelcastInstance) {
FilterRegistrationBean registration = new FilterRegistrationBean(new SpringAwareWebFilter());
registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
registration.addUrlPatterns("/*");
registration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE);
registration.addInitParameter("sticky-session", "false");
registration.addInitParameter("instance-name", hazelcastInstance.getName());
return registration;
}
#Bean
public ServletListenerRegistrationBean<SessionListener> hazelcastSessionListener() {
return new ServletListenerRegistrationBean<SessionListener>(new SessionListener());
}
From Main Class, I have excluded SessionAutoConfiguration.class
#SpringBootApplication
(exclude =
{
DataSourceAutoConfiguration.class,
HibernateJpaAutoConfiguration.class,
SessionAutoConfiguration.class
}
)
Below is my SecurityConfig.java
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/**
* Reference of UserDetailsService service class instance.
* #see UserDetailsService
*/
#Autowired
private UserDetailsService userDetailsService;
/**
* Reference of CustomAuthenticationSuccessHandler instance.
* #see CustomAuthenticationSuccessHandler
*/
#Autowired
private CustomAuthenticationSuccessHandler authenticationSuccessHandler;
/**
* Reference of CustomAuthenticationEntryPoint instance.
* #see CustomAuthenticationEntryPoint
*/
#Autowired
private CustomAuthenticationEntryPoint authenticationEntryPoint;
/**
* Reference of CustomAuthenticationFailureHandler instance.
* #see CustomAuthenticationFailureHandler
*/
#Autowired
private CustomAuthenticationFailureHandler authenticationFailureHandler;
/**
* Reference of CustomLogoutSuccessHandler instance.
* #see CustomLogoutSuccessHandler
*/
#Autowired
CustomLogoutSuccessHandler customLogoutSuccessHandler;
/**
* Reference of PasswordEncoder utility instance.
* #see PasswordEncoder
*/
#Autowired
private PasswordEncoder passwordEncoder;
#Autowired
private SessionRegistry sessionRegistry;
/**
* Method representing security configuration details, provides AuthenticationManager.
*
* #param auth Allows for easily building in memory authentication, LDAP authentication, JDBC based
* authentication, adding {#link UserDetailsService}, and adding
* AuthenticationProviders.
* #throws Exception
*/
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
}
/**
* Method returning a bean of AuthenticationManager which is available during application lifecycle.
*
* #return an instance of default AuthenticationManager.
* #throws Exception
*/
#Bean
public AuthenticationManager customAuthenticationManager() throws Exception {
return authenticationManager();
}
/**
* Method returning a bean of {#link ServletContextInitializer} to register {#link EventListener}s in a Servlet
* 3.0+ container.
*
* This bean can be used to register the following types of listener:
* <ul>
* <li>{#link ServletContextAttributeListener}</li>
* <li>{#link ServletRequestListener}</li>
* <li>{#link ServletRequestAttributeListener}</li>
* <li>{#link HttpSessionAttributeListener}</li>
* <li>{#link HttpSessionListener}</li>
* <li>{#link ServletContextListener}</li>
* </ul>
*
* #return ServletListenerRegistrationBean
*/
#Bean
public static ServletListenerRegistrationBean httpSessionEventPublisher() {
return new ServletListenerRegistrationBean(new HttpSessionEventPublisher());
}
/**
* Method returning a bean of custom authentication filter containing custom success and failure handlers.
* Also sets SessionAuthenticationStrategy in filter.
*
* #return CustomUsernamePasswordAuthenticationFilter
* #see CustomUsernamePasswordAuthenticationFilter
* #throws Exception
*/
#Bean
public CustomUsernamePasswordAuthenticationFilter authenticationFilter() throws Exception {
CustomUsernamePasswordAuthenticationFilter authenticationFilter
= new CustomUsernamePasswordAuthenticationFilter(sessionRegistry);
authenticationFilter.setAuthenticationSuccessHandler(authenticationSuccessHandler);
authenticationFilter.setAuthenticationFailureHandler(authenticationFailureHandler);
authenticationFilter.setRequiresAuthenticationRequestMatcher(
new AntPathRequestMatcher("/api/login", "POST"));
authenticationFilter.setAuthenticationManager(customAuthenticationManager());
authenticationFilter.setSessionAuthenticationStrategy(concurrentSession());
return authenticationFilter;
}
/**
* Method representing configuration/strategy for concurrent sessions.
*
* #return CompositeSessionAuthenticationStrategy A SessionAuthenticationStrategy that accepts multiple
* SessionAuthenticationStrategy implementations to delegate to. Each
* SessionAuthenticationStrategy is invoked in turn.
*/
#Bean
public CompositeSessionAuthenticationStrategy concurrentSession() {
ConcurrentSessionControlAuthenticationStrategy concurrentAuthenticationStrategy =
new ConcurrentSessionControlAuthenticationStrategy(sessionRegistry);
concurrentAuthenticationStrategy.setMaximumSessions(1);
concurrentAuthenticationStrategy.setExceptionIfMaximumExceeded(false);
List<SessionAuthenticationStrategy> delegateStrategies = new ArrayList<>();
delegateStrategies.add(concurrentAuthenticationStrategy);
delegateStrategies.add(new SessionFixationProtectionStrategy());
delegateStrategies.add(new RegisterSessionAuthenticationStrategy(sessionRegistry));
CompositeSessionAuthenticationStrategy authenticationStrategy =
new CompositeSessionAuthenticationStrategy(delegateStrategies);
return authenticationStrategy;
}
/**
* Method returning a bean of ConcurrentSessionFilter which is available during application life-cycle.
*
* #return ConcurrentSessionFilter
*/
#Bean
ConcurrentSessionFilter concurrentSessionFilter() {
CustomConcurrentSessionFilter concurrentSessionFilter = new CustomConcurrentSessionFilter(sessionRegistry);
return concurrentSessionFilter;
}
/**
* Method representing different types of security rules/configuration for the application.
*
* #param http HttpSecurity object to configure HTTP security parameters.
* #throws Exception
*/
#Override
protected void configure(HttpSecurity http) throws Exception {
http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);
http.sessionManagement().sessionAuthenticationStrategy(concurrentSession());
http.addFilterBefore(concurrentSessionFilter(), ConcurrentSessionFilter.class);
http.authorizeRequests()
.antMatchers("/api/secure/org/**",
"/v2/api-docs",
"/configuration/ui",
"/swagger-resources",
"/configuration/security",
"/swagger-ui.html",
"/webjars*//**//**",
"/swagger-resources/configuration/ui").
hasAnyAuthority("ADMIN").anyRequest().fullyAuthenticated()
.antMatchers("/api/secure/dms/**").
hasAnyAuthority("ADMIN","INTERNAL").anyRequest().fullyAuthenticated()
.antMatchers("/api/secure/ext/**","/api/secure/tests/**").
hasAnyAuthority("ADMIN","INTERNAL","EXT").anyRequest().fullyAuthenticated()
.and()
.addFilterBefore(
authenticationFilter(),
UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new RequestFilter(), BasicAuthenticationFilter.class)
/*.addFilterBefore(new RequestFilter(), BasicAuthenticationFilter.class)
.formLogin().loginPage("/api/login")
.permitAll()
.successHandler(authenticationSuccessHandler)
.failureHandler(authenticationFailureHandler)
.usernameParameter("email")
.passwordParameter("password")
.and()
.httpBasic().and()*/
.csrf().ignoringAntMatchers("/api/login","/api/auth/**","/api/secure/**")
.csrfTokenRepository(csrfTokenRepository())
.and()
.logout().logoutUrl("/api/logout")
.invalidateHttpSession(false).logoutSuccessHandler(customLogoutSuccessHandler)
.permitAll();
// http.logout().
// logoutUrl("/api/auth/logout").
// logoutSuccessHandler(customLogoutSuccessHandler);
//http.csrf().disable();
}
/**
* Method overriding/representing security configuration/rules to bypasses configured URLs.
*
* #param web WebSecurity object to apply rules.
*/
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/api/auth/**","/api/application/**","/api/unsecure/**");
}
/**
* This method configure global security.
*
* #param auth AuthenticationManagerBuilder object
* #throws Exception
*/
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
/**
* This method sets CSRF header name in CSRF token repository.
*
* #return CsrfTokenRepository repository object
*/
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
}
Can someone please suggest what set of configuration I am missing, or maybe if someone could share sample code or any resource with which I can configure it correctly.
Requirement is just to replicate sessions so that other cluster nodes are aware of existing sessions.
Thanks in advance!!!
Please check my sample project here: https://github.com/gokhanoner/seajug-demo
It uses Hazelcast as session cache as well using Spring Session, I believe it's what you needed & it's a simpler setup.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
Hi I added rest web service for my project..When I call to the rest service without login to my account, my rest services redirect to login page... How can I remove this feature for only web service URL.... Other URLs need to this security....
This is my security configuration
package lk.slsi.security.configuration;
import lk.slsi.security.services.AuthenticationService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.encoding.ShaPasswordEncoder;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import javax.servlet.http.HttpServletRequest;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
/**
* Created by ignotus on 1/26/2017.
*/
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private static final Logger logger = LogManager.getLogger(SecurityConfiguration.class);
#Autowired
private AuthenticationService authenticationService;
private RequestMatcher requestMatcher = new RequestMatcher() {
private AntPathRequestMatcher[] disableCsrfMatcher = {
new AntPathRequestMatcher("*/**")
};
#Override
public boolean matches(HttpServletRequest httpServletRequest) {
for (AntPathRequestMatcher match : disableCsrfMatcher) {
if (match.matches(httpServletRequest)) {
return false;
}
}
return true;
}
};
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/restservice/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/view/public/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and().logout().invalidateHttpSession(true)
.permitAll().logoutSuccessUrl("/");
http.csrf().disable();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
ShaPasswordEncoder encoder = new ShaPasswordEncoder(224);
try {
auth.userDetailsService(authenticationService).passwordEncoder(encoder);
} catch (Exception e) {
logger.error("Error Occurred while authentication. [{}]", e);
}
}
}
This is my rest service config class(JAX-RS)
#ApplicationPath("TransferPermit/SlsitoCustoms/")
public class restConfig extends Application{
}
This is my rest service controller
#Path("getby")
public class webServiceforCustoms {
#Autowired
private permitServices permitServices;
/**
* Creates a new instance of GenericResource
*/
public webServiceforCustoms() {
}
/**
* Retrieves representation of an instance of lk.slsi.GenericResource
*
* #param id
* #return an instance of java.lang.String
*/
#GET
#Produces(MediaType.APPLICATION_XML)
#Path("/date/{dtIssue}")
public List<CustomsPermit> getXmlbyDate(#PathParam("dtIssue") String dtIssue) {
List<CustomsPermit> permitRelease = permitServices.getPermitByDate(dtIssue);
return permitRelease;
}
#GET
#Produces(MediaType.APPLICATION_XML)
#Path("/id/{SNumber}")
public CustomsPermit getXmlbyEntryNo(#PathParam("SNumber") String SNumber) {
CustomsPermit permitRelease = permitServices.getPermitBySNumber(SNumber);
return permitRelease;
}
#GET
#Produces(MediaType.APPLICATION_XML)
#Path("/vatno/{importerVAT}")
public List<CustomsPermit> getXmlbyVATNo(#PathParam("importerVAT") String importerVAT) {
List<CustomsPermit> permitRelease = permitServices.getPermitByImporterVAT(importerVAT);
return permitRelease;
}
/**
* PUT method for updating or creating an instance of GenericResourcer
*
* #param content representation for the resource
*/
#PUT
#Consumes(MediaType.APPLICATION_XML)
public void putXml(String content) {
}
}
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/restservice/**");
}
Remove this from configure and add this
.antMatchers("/restservice/**"").permitAll()
I am implementing OAuth2 using spring boot. And followed this example for the same
Spring-oauth2-jpa-example
Video Tutorial
After implementing I have successfully able to generate access token. But the problem is when I try to access protected resource in my case /api. I am getting 404 not found.
Main Method
package com.gatimaanBoot;
import java.util.Arrays;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import com.gatimaanBoot.security.UserRepository;
#SpringBootApplication
public class GatimaanBootApplication {
#Autowired
private PasswordEncoder passwordEncoder;
public static void main(String[] args) {
System.out.println("booting....");
SpringApplication.run(GatimaanBootApplication.class, args);
}
/* #Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
return args -> {
System.out.println("Let's inspect the beans provided by Spring Boot:");
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
//System.out.println(beanName);
}
};
}*/
/**
* Password grants are switched on by injecting an AuthenticationManager.
* Here, we setup the builder so that the userDetailsService is the one we coded.
* #param builder
* #param repository
* #throws Exception
*/
#Autowired
public void authenticationManager(AuthenticationManagerBuilder builder, UserRepository repository, com.gatimaanBoot.security.service.UserService service) throws Exception {
//Setup a default user if db is empty
if (repository.count()==0)
service.save(new com.gatimaanBoot.security.entities.User("user", "user", Arrays.asList(new com.gatimaanBoot.security.entities.Role("USER"), new com.gatimaanBoot.security.entities.Role("ACTUATOR"))));
builder.userDetailsService(userDetailsService(repository)).passwordEncoder(passwordEncoder);
}
/**
* We return an instance of our CustomUserDetails.
* #param repository
* #return
*/
private UserDetailsService userDetailsService(final UserRepository repository) {
return username -> new CustomUserDetails(repository.findByUsername(username));
}
}
AuthorizationServer
/**
* Copyright 2017 Duronto Technology (P) Limited . All Rights Reserved.
* Duronto Technology PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package com.gatimaanBoot.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
/**
*
* #version 1.0, 09-Jul-2017
* #author Nikhil
*/
/**
* Configures the authorization server.
* The #EnableAuthorizationServer annotation is used to configure the OAuth 2.0 Authorization Server mechanism,
* together with any #Beans that implement AuthorizationServerConfigurer (there is a handy adapter implementation with empty methods).
*/
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private PasswordEncoder passwordEncoder;
/**
* Setting up the endpointsconfigurer authentication manager.
* The AuthorizationServerEndpointsConfigurer defines the authorization and token endpoints and the token services.
* #param endpoints
* #throws Exception
*/
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
/**
* Setting up the clients with a clientId, a clientSecret, a scope, the grant types and the authorities.
* #param clients
* #throws Exception
*/
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory().withClient("my-trusted-client")
.authorizedGrantTypes("password","authorization_code","implicit")
.authorities("ROLE_CLIENT","ROLE_TRUSTED_CLIENT").scopes("read","write","trust")
.resourceIds("oauth2-resource").accessTokenValiditySeconds(5000).secret("secret");
}
/**
* We here defines the security constraints on the token endpoint.
* We set it up to isAuthenticated, which returns true if the user is not anonymous
* #param security the AuthorizationServerSecurityConfigurer.
* #throws Exception
*/
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
}
}
ResourceServer
package com.gatimaanBoot.security;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
#Configuration
#EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.headers().frameOptions().disable().and()
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/api/**").authenticated();
}
}
Application.properties
#Application Path
server.contextPath = /gatimaanBoot
security.oauth2.resource.filter-order = 3
# Database
spring.datasource.driver = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/train?zeroDateTimeBehavior=convertToNull
spring.datasource.username = root
spring.datasource.password = root
# Hibernate
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQLDialect
spring.jpa.properties.hibernate.show_sql= true
spring.jpa.properties.hibernate.hbm2ddl.auto= update
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
Controller
/**
* Copyright 2017 Duronto Technology (P) Limited . All Rights Reserved.
* Duronto Technology PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package com.gatimaanBoot.station.controller;
/**
*
* #version 1.0, 24-Feb-2017
* #author Deepak Bisht
* #author Nikhil Mishra
*
*
*/
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.gatimaanBoot.station.dto.StationResponseDTO;
import com.gatimaanBoot.station.model.Station;
import com.gatimaanBoot.station.services.StationService;
#Controller
#RequestMapping("/api/")
public class StationController {
private static final Logger LOGGER = LoggerFactory.getLogger(StationController.class);
#Autowired
StationService stationService;
// get data for particular station
#RequestMapping(value = "/v1.0/station/{stationCode}/", method = RequestMethod.GET)
public #ResponseBody Station getStation(#PathVariable String stationCode) {
Station station = null;
try {
station = stationService.getStation(stationCode);
} catch (Exception e) {
e.printStackTrace();
}
return station;
}
/* Getting List of stations in Json format in pagination */
#RequestMapping(value = "/v1.0/station/", method = RequestMethod.GET)
public #ResponseBody List<Station> getStationList(
#RequestParam(value = "page", required = false, defaultValue = "0") int page) {
List<Station> stationList = null;
try {
stationList = stationService.getStationList(page);
} catch (Exception e) {
LOGGER.debug("Station Controller : " + e.getMessage());
e.printStackTrace();
}
return stationList;
}
// insert new station
#RequestMapping(value = "/v1.0/station/", method = RequestMethod.POST)
public #ResponseBody StationResponseDTO insertStation(#RequestBody Station station) {
StationResponseDTO stationDTO = null;
try {
stationDTO = stationService.insertStation(station);
} catch (Exception e) {
e.printStackTrace();
}
return stationDTO;
}
// insert new station
#RequestMapping(value = "/v1.0/station/", method = RequestMethod.PUT)
public #ResponseBody StationResponseDTO updateStation(#RequestBody Station station) {
StationResponseDTO stationDTO = null;
try {
stationDTO = stationService.updateStation(station);
} catch (Exception e) {
e.printStackTrace();
}
return stationDTO;
}
// delete a station
#RequestMapping(value = "/v1.0/station/", method = RequestMethod.DELETE)
public #ResponseBody StationResponseDTO deleteStation(#RequestBody Station station) {
StationResponseDTO stationDTO = null;
try {
stationDTO = stationService.deleteStation(station);
} catch (Exception e) {
e.printStackTrace();
}
return stationDTO;
}
#RequestMapping(value = "/v1.0/station/list/", method = RequestMethod.POST)
public #ResponseBody List<Station> getTrainList(#RequestBody ArrayList<String> stationList) {
return stationService.getStationListBulk(stationList);
}
}
Thanks.