I have very strange problem. In simple project I used Spring-Boot with oAuth2 (it is exactly jhipster generated project).
In services I connect with remote controllers (remote API) by restTemplate class. And I created special class to store cookieSession access to this remote API (this class has Session scope).
During authorization I save cookieSession from remote API to Session Scope class, and then when I make request to other part of remote API I use this seesionCookie.
Problem is, when I make asynchronous requesting from AngulrJS then sometimes Session scope class exist and sometimes it doesn't have data (is empty), but when I refresh website I have this data (without making next authorization). Whan I make synchronous requests there is no problem.
#Service
#Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class AuthorizationOsipDataService implements Serializable {
private String cookieSession;
public String getCookieSession() {
return cookieSession;
}
public void setCookieSession(String cookieSession) {
this.cookieSession = cookieSession;
}
}
Service:
#Service
public class OsipService {
#Autowired
private RestTemplate restTemplate;
#Autowired
private AuthorizationOsipDataService authorizationOsipDataService;
public String signInToOsipAndGetCookieSession (String login, String password) throws SignInToOsipException {
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("j_username", login);
map.add("j_password", password);
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<MultiValueMap<String, String>>(map, new HttpHeaders());
log.debug("Logging... user: '{}'", login);
ResponseEntity response = restTemplate.exchange(osipUrl + authorizationUrl, HttpMethod.POST, requestEntity, String.class);
if(isLogged(response)){
String cookieSession = response.getHeaders().getFirst(HttpHeaders.SET_COOKIE);
log.debug("Succes login, setting authorizationOsipDataService");
authorizationOsipDataService.setPassword(password);
authorizationOsipDataService.setUsername(login);
authorizationOsipDataService.setCookieSession(cookieSession);
selectCompanyContext("538880bde511f776304687e6");
if(hasRoleOsipLite().getBody()){
return cookieSession;
} else {
throw new SignInToOsipException("User doesn't has ROLE_OSIPLITE");
}
} else{
throw new SignInToOsipException("Login error, HttpSatus:"+ response.getStatusCode().toString());
}
}
private boolean isLogged(ResponseEntity response){
//if location contains '/signin', it means that there is redirect and signin is failed
return !response.getHeaders().getFirst(HttpHeaders.LOCATION).contains("osip/signin");
}
public ResponseEntity selectCompanyContext(String companyContextId){
HttpHeaders httpHeaders = makeHeadersWithJson();
HttpEntity<String> requestEntity = new HttpEntity<String>(httpHeaders);
log.debug("Selecting context... '{}' ", companyContextId);
return restTemplate.exchange(osipUrl + selectCompanyContextUrl + companyContextId, HttpMethod.GET, requestEntity, String.class);
}
public ResponseEntity<NipExistDTO> isExistNip(String nip){
HttpHeaders httpHeaders = makeHeadersWithJson();
HttpEntity<String> requestEntity = new HttpEntity<String>(httpHeaders);
log.debug("isExistTest for nip: '{}'", nip);
return restTemplate.exchange(osipUrl + existNipUrl + nip, HttpMethod.GET, requestEntity, NipExistDTO.class);
}
}
...
...
...
Controllers:
#RestController
#RequestMapping("/customer")
public class CustomerResource {
private final Logger log = LoggerFactory.getLogger(CustomerResource.class);
#Autowired
private OsipService osipService;
#RequestMapping(value = "nipExist", method = RequestMethod.GET)
public
#ResponseBody
ResponseEntity<NipExistDTO> isNipExist(#RequestParam String nip) throws SignInToOsipException {
return osipService.isExistNip(nip);
}
#RequestMapping(value = "add", method = RequestMethod.POST)
public
#ResponseBody
ResponseEntity addCustomer(#RequestBody NewCustomerDTO newCustomerDTO) throws SignInToOsipException {
return osipService.addCustomerToOsip(newCustomerDTO);
}
}
WebConfig (configuration of Session Scope)
public void onStartup(ServletContext servletContext) throws ServletException {
log.info("Web application configuration, using profiles: {}", Arrays.toString(env.getActiveProfiles()));
EnumSet<DispatcherType> disps = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.ASYNC);
if (!env.acceptsProfiles(Constants.SPRING_PROFILE_FAST)) {
initMetrics(servletContext, disps);
}
if (env.acceptsProfiles(Constants.SPRING_PROFILE_PRODUCTION)) {
initCachingHttpHeadersFilter(servletContext, disps);
initStaticResourcesProductionFilter(servletContext, disps);
initGzipFilter(servletContext, disps);
}
log.info("Web application fully configured");
servletContext.addListener(new RequestContextListener());
}
AngularJS
angular.module('osipliteApp')
.controller('CustomerController', function ($rootScope, $scope, Upload, $timeout,Customer,Scenario,Dictionary,$loading,$state,Auth) {
$loading.start('addCustomer');
$scope.isCollapsed=true;
//**** Initializing fields ****//
$scope.customerDTO = {name: null, nip: null, street: null,streetNumber:null, postOffice:null, zipCode:null, phoneNumber1: null, surveyNotes:null};
$scope.personEditDTO = {name: null, email:null,code1:null, phone1:null};
$scope.newCustomerDTO = {customerType: null, scenarioId:null};
$scope.personEditDTO.code1= '+48';
$scope.customerTypes = [{name:"Osoba fizyczna",value:"NATURAL_PERSON"},{name:"Jednostka budżetowa",value:"BUDGETARY_UNITS"},{name:"Spółka prawa handlowego",value:"COMMERCIAL"},{name:"Osoba fizyczna prowadząca działalność gospodarczą",value:"NATURAL_PERSON_WITH_BUSINESS"}];
$scope.products = Dictionary.get({dictionaryCode: 'PRODUCT_TYPE',languageCode:"PL"},function(success){
$scope.scenariosList = Scenario.get({value:'active'},function(success){$loading.finish('addCustomer');},function(error){restErrorHandler(error);});
},function(error){restErrorHandler(error);});
$scope.clear = function () {
$scope.customerDTO = {name: null, nip: null, street: null,streetNumber:null, postOffice:null, zipCode:null, phoneNumber1: null, surveyNotes:null};
$scope.personEditDTO = {name: null, email:null,code1:"+48", phone1:null};
$scope.newCustomerDTO = {customerType: "NATURAL_PERSON", scenarioId:null};
$scope.nipInvalid = null;
$scope.nipExist = null;
clearSurvey();
};
...
...
Related
The content from MockMvc managed to have status code but missing the data.
Test class:
#Test
public void shouldReturnAll() throws Exception {
when(userService.getAll()).thenReturn(users); // note that 'users' is not empty, I already checked.
MvcResult response = this.mvc.perform(get("/users"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data", hasSize(2)))
.andReturn();
}
Reponse:
MockHttpServletResponse:
Status = 200
Error message = null
Headers = [Content-Type:"application/json"]
Content type = application/json
Body = {"status":"success"}
Forwarded URL = null
Redirected URL = null
Cookies = []
I think it has something to do with Response object in my Controller class.
Controller:
#GetMapping
public ResponseEntity<Response> getAll() {
List<User> users = userService.getAll();
Response resp = new Response(StatusMessage.SUCCESS, users);
return new ResponseEntity<Response>(resp, HttpStatus.OK);
}
Edit: Another test which works (getting a single User):
#Test
public void getUserByIdTest() throws Exception {
when(this.userService.getUserById(any(Long.class))).thenReturn(user);
MvcResult response = this.mvc.perform(get("/users/{id}", user.getId()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.id", is(user.getId().intValue())))
.andExpect(jsonPath("$.data.name", is(user.getName())))
.andReturn();
}
Controller:
#GetMapping(value = "/{id}")
public ResponseEntity<Response> getUserById(#PathVariable Long id) throws Exception {
try {
User user = userService.getUserById(id);
Response resp = new Response(StatusMessage.SUCCESS, user);
return new ResponseEntity<Response>(resp, HttpStatus.OK);
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}
Response object class:
#Data
#JsonInclude(JsonInclude.Include.NON_EMPTY)
public class Response<T> {
private String status;
private T data;
public Response(StatusMessage status, T data) {
this.status = status.getStatusMessage();
this.data = data;
}
I wanna run a schedule method and in this method I need to use information about user is logged in. However, when I run getPrincipal() my code gets nullPointException
#Component
public class Import extends WebSecurityConfigurerAdapter {
#Autowired
private ActivityRepository activityRepository;
#Scheduled(fixedRate = 300000)
public void importActivities() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Principal principal = (Principal) authentication.getPrincipal();
List<Activity> lastActivity = activityRepository.findFirstByOrderByStartDateDesc();
int lastEpoch = 0;
if (lastActivity.isEmpty() == false) {
lastEpoch = (int) (lastActivity.get(0).getStartDate().getTime() / 1000);
}
System.out.println(lastEpoch);
final RestTemplate restTemplate = new RestTemplate();
final HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(getAccessToken(principal));
final HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
ResponseEntity<List<Activity>> rateResponse = restTemplate.exchange(
"https://www.strava.com/api/v3/athlete/activities?after=" + lastEpoch, HttpMethod.GET, entity,
new ParameterizedTypeReference<List<Activity>>() {
});
List<Activity> activities = rateResponse.getBody();
activityRepository.saveAll(activities);
}
private String getAccessToken(final Principal principal) {
final OAuth2Authentication oauth2Auth = (OAuth2Authentication) principal;
final OAuth2AuthenticationDetails oauth2AuthDetails = (OAuth2AuthenticationDetails) oauth2Auth.getDetails();
return oauth2AuthDetails.getTokenValue();
}
}
Thanks
I have created a Spring Restful Service and Spring MVC application.
Restful Service ::
Restful service returns an entity if its existing in DB. If it doesn't exist It returns a custom Exception information in ResponseEntity object.
It is working as expected tested using Postman.
#GetMapping(value = "/validate/{itemId}", produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE })
public ResponseEntity<MyItem> validateItem(#PathVariable Long itemId, #RequestHeader HttpHeaders httpHeaders) {
MyItem myItem = myitemService.validateMyItem(itemId);
ResponseEntity<MyItem> responseEntity = null;
if (myItem == null) {
throw new ItemNotFoundException("Item Not Found!!!!");
}
responseEntity = new ResponseEntity<MyItem>(myItem, headers, HttpStatus.OK);
return responseEntity;
}
If the requested Entity does not exist Restful Service returns below.
#ExceptionHandler(ItemNotFoundException.class)
public ResponseEntity<ExceptionResponse> itemNotFEx(WebRequest webRequest, Exception exception) {
System.out.println("In CREEH::ItemNFE");
ExceptionResponse exceptionResponse = new ExceptionResponse("Item Not Found Ex!!!", new Date(), webRequest.getDescription(false));
ResponseEntity<ExceptionResponse> responseEntity = new ResponseEntity<ExceptionResponse>(exceptionResponse, HttpStatus.NOT_FOUND);
return responseEntity;
}
But when I am calling the above service from a spring MVC application using RestTemplate, It is returning a valid object if it exists.
If the requested object does not exist Restful service is returning the exception information but its not reaching the calling(spring MVC) application.
Spring MVC application calls Restful Web Service using Rest template
String url = "http://localhost:8080/ItemServices/items/validate/{itemId}";
ResponseEntity<Object> responseEntity = restTemplate.exchange(url, HttpMethod.GET, httpEntity, Object.class, uriParms);
int restCallStateCode = responseEntity.getStatusCodeValue();
This is expected behavior. Rest template throws exception when the http status is client error or server error and returns the response when http status is not error status.
You have to provide implementation to use your error handler, map the response to response entity and throw the exception.
Create new error exception class with ResponseEntity field.
public class ResponseEntityErrorException extends RuntimeException {
private ResponseEntity<ErrorResponse> errorResponse;
public ResponseEntityErrorException(ResponseEntity<ErrorResponse> errorResponse) {
this.errorResponse = errorResponse;
}
public ResponseEntity<ErrorResponse> getErrorResponse() {
return errorResponse;
}
}
Custom error handler which maps the error response back to ResponseEntity.
public class ResponseEntityErrorHandler implements ResponseErrorHandler {
private List<HttpMessageConverter<?>> messageConverters;
#Override
public boolean hasError(ClientHttpResponse response) throws IOException {
return hasError(response.getStatusCode());
}
protected boolean hasError(HttpStatus statusCode) {
return (statusCode.is4xxClientError() || statusCode.is5xxServerError());
}
#Override
public void handleError(ClientHttpResponse response) throws IOException {
HttpMessageConverterExtractor<ExceptionResponse> errorMessageExtractor =
new HttpMessageConverterExtractor(ExceptionResponse.class, messageConverters);
ExceptionResponse errorObject = errorMessageExtractor.extractData(response);
throw new ResponseEntityErrorException(ResponseEntity.status(response.getRawStatusCode()).headers(response.getHeaders()).body(errorObject));
}
public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
this.messageConverters = messageConverters;
}
}
RestTemplate Configuration - You have to set RestTemplate's errorHandler to ResponseEntityErrorHandler.
#Configuration
public class RestTemplateConfiguration {
#Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
ResponseEntityErrorHandler errorHandler = new ResponseEntityErrorHandler();
errorHandler.setMessageConverters(restTemplate.getMessageConverters());
restTemplate.setErrorHandler(errorHandler);
return restTemplate;
}
}
Calling Method
#Autowired restTemplate
String url = "http://localhost:8080/ItemServices/items/validate/{itemId}";
try {
ResponseEntity<Object> responseEntity = restTemplate.exchange(url, HttpMethod.GET, httpEntity, Object.class, uriParms);
int restCallStateCode = responseEntity.getStatusCodeValue();
} catch (ResponseEntityErrorException re) {
ResponseEntity<ErrorResponse> errorResponse = re.getErrorResponse();
}
Try using the #ResponseBody annotation on your Exceptionhandler. e.g:
public #ResponseBody ResponseEntity<ExceptionResponse> itemNotFEx(WebRequest webRequest, Exception exception) {... }
You should use Custom Exception Handler to fix your case. It looks like this
#ControllerAdvice
public class CustomResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
public CustomResponseEntityExceptionHandler() {
super();
}
// 404
#ExceptionHandler(value = { EntityNotFoundException.class, ResourceNotFoundException.class })
protected ResponseEntity<Object> handleNotFound(final RuntimeException ex, final WebRequest request) {
BaseResponse responseError = new BaseResponse(HttpStatus.NOT_FOUND.value(),HttpStatus.NOT_FOUND.name(),
Constants.HttpStatusMsg.ERROR_NOT_FOUND);
logger.error(ex.getMessage());
return handleExceptionInternal(ex, responseError, new HttpHeaders(), HttpStatus.NOT_FOUND, request);
}
}
And your code should throw some exception, eg:
if (your_entity == null) {
throw new EntityNotFoundException("said something");
}
If you get this case in somewhere else again, you just throw exception like above. Your handler will take care the rest stuffs.
Hope this help.
I've started your application and works just fine.
Maven :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
The controller class is :
#Controller
public class ValidationController {
#GetMapping(value = "/validate/{itemId}")
public #ResponseBody ResponseEntity<MyItem> validateItem(#PathVariable Long itemId) {
if (itemId.equals(Long.valueOf(1))) {
throw new ItemNotFoundException();
}
return new ResponseEntity<>(new MyItem(), HttpStatus.OK);
}
#ExceptionHandler(ItemNotFoundException.class)
public ResponseEntity<ExceptionResponse> itemNotFEx(WebRequest webRequest, Exception exception) {
System.out.println("In CREEH::ItemNFE");
ExceptionResponse exceptionResponse = new ExceptionResponse("Item Not Found Ex!!!", new Date(), webRequest.getDescription(false));
ResponseEntity<ExceptionResponse> responseEntity = new ResponseEntity<>(exceptionResponse, HttpStatus.NOT_FOUND);
return responseEntity;
}
}
and the test:
#RunWith(SpringRunner.class)
#WebMvcTest(value = ValidationController.class, secure = false)
public class TestValidationController {
#Autowired
private MockMvc mockMvc;
#Test
public void testExpectNotFound() throws Exception {
mockMvc.perform(get("/validate/1"))
.andExpect(status().isNotFound());
}
#Test
public void testExpectFound() throws Exception {
mockMvc.perform(get("/validate/2"))
.andExpect(status().isOk());
}
}
Are you sure the url you are trying to use with RestTemplate is correct?
String url = "http://localhost:8080/ItemServices/items/validate/{itemId}";
Your get method is #GetMapping(value = "/validate/{itemId}"
If you don't have request mapping at the level of the controller the url should be:
http://localhost:8080/validate/1
Another difference is the missing #ResponseBody on your controller method.
I have a microservice architecture, both of them securized by spring security an JWT tokens.
So, when I call my first microservice, I want to take the JWT token and send a request to another service using those credentials.
How can I retrieve the token and sent again to the other service?
Basically your token should be located in the header of the request, like for example: Authorization: Bearer . For getting it you can retrieve any header value by #RequestHeader() in your controller:
#GetMapping("/someMapping")
public String someMethod(#RequestHeader("Authorization") String token) {
}
Now you can place the token within the header for the following request:
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", token);
HttpEntity<RestRequest> entityReq = new HttpEntity<RestRequest>(request, headers);
Now you can pass the HttpEntity to your rest template:
template.exchange("RestSvcUrl", HttpMethod.POST, entityReq, SomeResponse.class);
Hope I could help
I've accomplished the task, creating a custom Filter
public class RequestFilter implements Filter{
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String token = httpServletRequest.getHeader(RequestContext.REQUEST_HEADER_NAME);
if (token == null || "".equals(token)) {
throw new IllegalArgumentException("Can't retrieve JWT Token");
}
RequestContext.getContext().setToken(token);
chain.doFilter(request, response);
}
#Override
public void destroy() { }
#Override
public void init(FilterConfig arg0) throws ServletException {}
}
Then, setting in my config
#Bean
public FilterRegistrationBean getPeticionFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new RequestFilter());
registration.addUrlPatterns("/*");
registration.setName("requestFilter");
return registration;
}
With that in mind, I've create another class with a ThreadLocal variable to pass the JWT token from the Controller to the Rest Templace interceptor
public class RequestContext {
public static final String REQUEST_HEADER_NAME = "Authorization";
private static final ThreadLocal<RequestContext> CONTEXT = new ThreadLocal<>();
private String token;
public static RequestContext getContext() {
RequestContext result = CONTEXT.get();
if (result == null) {
result = new RequestContext();
CONTEXT.set(result);
}
return result;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}
public class RestTemplateInterceptor implements ClientHttpRequestInterceptor{
#Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
String token = RequestContext.getContext().getToken();
request.getHeaders().add(RequestContext.REQUEST_HEADER_NAME, token);
return execution.execute(request, body);
}
}
Add interceptor to the config
#PostConstruct
public void addInterceptors() {
List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();
interceptors.add(new RestTemplateInterceptor());
restTemplate.setInterceptors(interceptors);
}
I think it is better to add the interceptor specifically to the RestTemplate, like this:
class RestTemplateHeaderModifierInterceptor(private val authenticationService: IAuthenticationService) : ClientHttpRequestInterceptor {
override fun intercept(request: org.springframework.http.HttpRequest, body: ByteArray, execution: ClientHttpRequestExecution): ClientHttpResponse {
if (!request.headers.containsKey("Authorization")) {
// don't overwrite, just add if not there.
val jwt = authenticationService.getCurrentUser()!!.jwt
request.headers.add("Authorization", "Bearer $jwt")
}
val response = execution.execute(request, body)
return response
}
}
And add it to the RestTemplate like so:
#Bean
fun restTemplate(): RestTemplate {
val restTemplate = RestTemplate()
restTemplate.interceptors.add(RestTemplateHeaderModifierInterceptor(authenticationService)) // add interceptor to send JWT along with requests.
return restTemplate
}
That way, every time you need a RestTemplate you can just use autowiring to get it. You do need to implement the AuthenticationService still to get the token from the TokenStore, like this:
val details = SecurityContextHolder.getContext().authentication.details
if (details is OAuth2AuthenticationDetails) {
val token = tokenStore.readAccessToken(details.tokenValue)
return token.value
}
May be a little bit late but I think this is a common question, regarding
Spring Security 6.0.0 for web client there is a class called ServletBearerExchangeFilterFunction that you can use to read the token from the security context and inject it.
#Bean
public WebClient rest() {
return WebClient.builder()
.filter(new ServletBearerExchangeFilterFunction())
.build();
For RestTemplate there is no automatic way and is recommended use a filter
#Bean
RestTemplate rest() {
RestTemplate rest = new RestTemplate();
rest.getInterceptors().add((request, body, execution) -> {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null) {
return execution.execute(request, body);
}
if (!(authentication.getCredentials() instanceof AbstractOAuth2Token)) {
return execution.execute(request, body);
}
AbstractOAuth2Token token = (AbstractOAuth2Token) authentication.getCredentials();
request.getHeaders().setBearerAuth(token.getTokenValue());
return execution.execute(request, body);
});
return rest;
}
I'm writing an messenger with JavaFX and Spring4 on client-site and Spring4 on server-site. I secured the server with spring-security 3.2. Now my Problem: I have a loginpage on the client witch sends the login information to spring-security and receive the JSESSIONID cookie. This works fine but when I try to send the JSESSIONID with my request I become an
org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class org.messenger.rest.JSONConversationResult] and content type [text/html;charset=UTF-8]
Server Inizializer
public class SpringMvcInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] {ApplicationConfig.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] {WebConfig.class};
}
#Override
protected String[] getServletMappings() {
return new String[] {"/"};
}
}
Server SecurityInizializer
public class SpringSecurityInitializer extends
AbstractSecurityWebApplicationInitializer {
}
Server SecurityConfig
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private DriverManagerDataSource dataSource;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
String authQuery = "select userid, authority from user where userid = ?";
String userQuery = "select userid, pw, enabled from user where userid = ?";
auth.jdbcAuthentication().dataSource(dataSource)
.passwordEncoder(passwordEncoder())
.usersByUsernameQuery(userQuery)
.authoritiesByUsernameQuery(authQuery);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/register").permitAll()
.antMatchers("/getconvs", "/getcontacts").hasRole("USER")
.and()
.formLogin()
.and()
.csrf().disable();
}
#Bean
public AuthenticationEntryPoint authenticationEntryPoint() {
return new de.daschner.messenger.security.AuthenticationEntryPoint();
}
#Bean
public SuccessHandler successHandler() {
return new SuccessHandler();
}
#Bean
public SimpleUrlAuthenticationFailureHandler failureHandler() {
return new SimpleUrlAuthenticationFailureHandler();
}
#Bean
public AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(11);
}
}
Server requestmapping for the secured "page"
#RequestMapping(value="/getconvs", method={RequestMethod.GET},
produces={MediaType.APPLICATION_JSON_VALUE})
public #ResponseBody JSONConversationResult getConvsList(HttpServletRequest request, #RequestParam(value="uid") String uid){
JSONConversationResult ret = new JSONConversationResult();
Map<String, Map<Date, String>> convs = convService.getConvsList(uid);
if (convs != null) {
ret.setConversations(convs);
ret.setMessage("OK");
ret.setError(0);
} else {
ret.setError(1);
ret.setMessage("Verbindungsfehler");
}
return ret;
}
Client send Login and get Cookie
Map<String, String> loginform = new HashMap<String, String>();
loginform.put("username", user);
loginform.put("password", pw);
HttpEntity<Map<String, String>> login = new HttpEntity<Map<String, String>>(loginform);
ResponseEntity<HttpServletResponse> response = restTemplate.exchange(
"http://localhost:8080/messenger-webapp/login",
HttpMethod.POST,
login,
HttpServletResponse.class);
HttpHeaders headers = response.getHeaders();
Set<String> keys = headers.keySet();
String cookie = "";
for (String header : keys) {
if (header.equals("Set-Cookie")) {
cookie = headers.get(header).get(0);
}
}
String jsessionid = cookie.split(";")[0];
conf.setJsessionid(jsessionid.split("=", 2)[1]);
return ret;
Client send JSESSIONID with request
ResponseEntity<JSONConversationResult> response = restTemplate.exchange(
"http://localhost:8080/messenger-webapp/getconvs?uid=" + uid,
HttpMethod.GET,
getAuthHeader(),
JSONConversationResult.class);
JSONConversationResult ret = response.getBody();
return ret;
private HttpEntity<String> getAuthHeader() {
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add("Cookie", "JSESSIONID=" + config.getJsessionid());
return new HttpEntity<String>(requestHeaders);
}
I hope you can help me.
EDIT:
Ok I figured out that the problem was not that the JSESSIONID wasn't sent correctly. But my login was incorrect and my query to get the user from database.
The correct login-post
ClientHttpResponse response = restTemplate.execute(
"http://localhost:8080/messenger-webapp/login",
HttpMethod.POST,
new RequestCallback() {
#Override
public void doWithRequest(ClientHttpRequest request) throws IOException {
request.getBody().write(("username=" + user + "&password=" + pw).getBytes());
}
},
new ResponseExtractor<ClientHttpResponse>() {
#Override
public ClientHttpResponse extractData(ClientHttpResponse response)
throws IOException {
return response;
}
});
The correct query
String authQuery = "select u.userid, r.role_name from user u, role r, user_role a where u.dbid = a.user_id and r.dbid = a.role_id and u.userid = ?";
I hope this will help other people. If anyone has an alternative please let me know.
Ok I figured out that the problem was not that the JSESSIONID wasn't sent correctly. But my login was incorrect and my query to get the user from database.
The correct login-post
ClientHttpResponse response = restTemplate.execute(
"http://localhost:8080/messenger-webapp/login",
HttpMethod.POST,
new RequestCallback() {
#Override
public void doWithRequest(ClientHttpRequest request) throws IOException {
request.getBody().write(("username=" + user + "&password=" + pw).getBytes());
}
},
new ResponseExtractor<ClientHttpResponse>() {
#Override
public ClientHttpResponse extractData(ClientHttpResponse response)
throws IOException {
return response;
}
});
The correct query
String authQuery = "select u.userid, r.role_name from user u, role r, user_role a where u.dbid = a.user_id and r.dbid = a.role_id and u.userid = ?";
I hope this will help other people. If anyone has an alternative please let me know.