Getting current logged user in spring + angular - java

I am using Spring Security in my Spring Boot app and i want to get the current logged user from Principal#getName but i have an error of template resolution and it contains the username that i want to get.
This is my controller:
import java.security.Principal;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
#Controller
public class PageController {
#RequestMapping(value = "/api/loggeduser", method = RequestMethod.GET)
public String printWelcome(ModelMap model, Principal principal) {
String name = null;
if (principal !=null) {
name = principal.getName();
}
model.addAttribute("username", name);
return name;
}
}
And this is my AngularJs function to get the logged in user:
app.controller('Usercontr', function($scope, $http) {
$http.get("/api/loggeduser").success(function (data) {
$scope.nom = data;
console.log($scope.nom)
})
});
And here's the error:
Error resolving template "kamel.mili", template might not exist or
might not be accessible by any of the configured Template Resolvers
Kamel.mili is the logged in username. Can you please help me. I am using thymeleaf for just the login page and everything else is html + AngularJs. I don't know why thymeleaf had it's hand on this controller.

Add a #ResponseBody annotation to your controller:
#ResponseBody
#RequestMapping(value = "/api/loggeduser", method = RequestMethod.GET)
public String printWelcome(ModelMap model, Principal principal ) { ... }
When you're using the #Controller stereotype annotation, Spring MVC will try to resolve your String return value to a View, hence the error:
Error resolving template "kamel.mili", template might not exist or
might not be accessible by any of the configured Template Resolvers
If you want to just write the return value to the response body, you can either make your controller a #RestController or annotate specific controllers with #ResponseBody.
This is kinda off topic but since you're using client side view rendering, that ModelMap is pretty useless. You can safely get rid of it.

You need to do like following:
#RequestMapping(value = "/api/loggeduser", produces =MediaType.APPLICATION_JSON_VALUE )
public ResponseEntity<String> findMessagesForUser(Principal principal) {
return new ResponseEntity<String>(principal.getName(), HttpStatus.OK);
}
Or you can use response builders:
#RequestMapping(value = "/api/loggeduser", produces =MediaType.APPLICATION_JSON_VALUE )
public ResponseEntity<String> findMessagesForUser(Principal principal) {
return ResponseEntity.ok(principal.getName());
}

If you have properly configured template resolver, then you should check yours templates. Return string from printWelcome() should match with one of the view created in your view/template folder.In your case, you are returning user name it self, i guess it should be welcome kind of page.

Related

Spring Boot test API endpoint with unit testing should return 404 instead of 400

I have the following controller on my Spring Boot application, which is connected to a MongoDB:
#RestController
#RequestMapping("/experts")
class ExpertController {
#Autowired
private ExpertRepository repository;
#RequestMapping(value = "/", method = RequestMethod.GET)
public List<Experts> getAllExperts() {
return repository.findAll();
}
#RequestMapping(value = "/{id}", method = RequestMethod.GET)
public Experts getExpertById(#PathVariable("id") ObjectId id) {
return repository.findBy_id(id);
}
I am trying to test the the get/id endpoint on my test, which I expect to give back an 404 response as shown below:
#Test
public void getEmployeeReturn404() throws Exception {
ObjectId id = new ObjectId();
mockMvc.perform(MockMvcRequestBuilders.get("/experts/999", 42L)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isNotFound());
}
Despite that, the response that comes back is 400, which means that my request is malformed. I guess the problem lies on the id, which I am inputting on the URI? I know that mongo accepts hexStrings as primary keys so my question is, how could I use an id on the URI which doesnt exist on my DB so that I can get a 404 response back? Thanks in advance for your answer.
"/experts/999", 42L
This is not an objectId.
Try something like
mockMvc.perform(MockMvcRequestBuilders.get("/experts/58d1c36efb0cac4e15afd278")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isNotFound());
For urlVariables, you need:
#Test
public void getEmployeeReturn404() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/experts/{id}", 42L)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isNotFound());
}
Where 42L is your {id} PathVariable value.

Receiving a POST Request on Spring From Another Site

I'm a little new in Java Spring. What I want to do is as follows:
Some 3rd party is asking a "return URL" from me and I set it as follows:
https://localhost:9002/my-account/order-history
Then they send me a POST request and I'm supposed to handle it within my controller. The request has both url parameters and a form data. The request is
Request URL:https://localhost:9002/my-account/order-history?responseCode=0000&token=E0ECFC1214B19E5D11B9B587920FC5F164C5CB17E7DC67F083E0EC6676F79467DFBDF4B6CCF3C39BF47F0232D1AA42F1FA112F29B0157DDF98EE3997F781CCB1FEB070A44E530691BA36674BEA4CF56A4A43F2B9746D9C3591CF288D745A6694
Request Method:POST
Status Code:403 Bad or missing CSRF token
Remote Address:127.0.0.1:9002
Referrer Policy:no-referrer-when-downgrade
A part of the form data is:
I added the whole form data and other request info as attachment.
The controller I'm desperately trying to use is as follows:
#Controller
#RequestMapping(value = "/my-account")
public class MaviAccountPageController extends MaviAbstractController
{
#RequestMapping(value = "/order-history", method = RequestMethod.POST)
public ModelAndView process(#RequestBody final String req)
{
//consumes = "text/plain"
System.out.println(req);
System.out.println(req);
return new ModelAndView("deneme");
}
....
}
And I keep getting 403 - Bad or missing CSRF token error.
How should I implement my controller? I have checked below links and they did not work out unfortunately:
How to retrieve FORM/POST Parameters in Spring Controller?
How to explicitly obtain post data in Spring MVC?
I tried, but failed to regenerate issue on postman.
Can anyone, please, advise me about how to move on?
you can annotate your method with #CrossOrigin
#CrossOrigin
#RequestMapping(value = "/order-history", method = RequestMethod.POST)
public ModelAndView process(#RequestBody final String req)
{
//consumes = "text/plain"
System.out.println(req);
System.out.println(req);
return new ModelAndView("deneme");
}
https://spring.io/guides/gs/rest-service-cors/

How do I add attributes to http request to spring controller?

I would like to test the spring controller below, which reads http request attributes and acts on them. I am able to trigger the controller code below by typing localhost:8080/someURL into my web browser. But the result is {"id":1,"content":"null and null and null"}, which indicate null values in the named request attributes. How do I send a request to a named url like localhost:8080/someURL which contains values for the specified request attributes, so that I can confirm that the receiving controller code works properly?
Here is the code for the controller:
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestPa ram;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
#Controller
public class SomeController {
private final AtomicLong counter = new AtomicLong();
#RequestMapping(value = "/someURL", method=RequestMethod.GET)
public #ResponseBody Greeting receiveSMS(HttpServletRequest req){
String att1 = (String) req.getAttribute("att1");
String att2 = (String) req.getAttribute("att2");
String att3 = (String) req.getAttribute("att3");
String total = att1 + " and " + att2 + " and " + att3;
return new Greeting(counter.incrementAndGet(), String.format(total));
}
}
Note: I am trying to recreate in Spring the PHP functionality that is given in the script at the following link. I have not written this kind of code below, if I am framing the question poorly, I would appreciate advice for reframing it. Along with a link to any example solution such as a JUNIT or other means by which to recreate the request.
Request attributes are server-side only constructs. Try using request parameters instead:
#RequestMapping(value = "/someURL", method = RequestMethod.GET)
public #ResponseBody Greeting receiveSMS(#RequestParam("att1") String att1, #RequestParam("att2") String att2, #RequestParam("att3") String att3){
String total = String.format("%s and %s and %s", att1, att2, att3);
return new Greeting(counter.incrementAndGet(), total);
}
Then send a request of the form:
http://localhost:8080/someURL?att1=value1&att2=value2&att3=value3
And you should be able to read the values that you are trying to pass.
Checkout Spring MVC Test framework - instead of manually fire some URLs write unit tests instead.
Regarding your note
Yes, that's parameters. In php you have $_GET and $_POST or (if you don't care about the method) simply $_REQUEST for accessing the request parameters. Recode from getAttribute() to getParameter() or put them in your method signature using #RequestParam annotation.
#RequestMapping(value = "/receiveSMS", method=RequestMethod.GET)
public #ResponseBody Greeting receiveSMS(#RequestParam("from") String from,
#RequestParam("to") String to, #RequestParam("body") String body){
}
Now you can try http://localhost:8080/yourapp/receiveSMS?from=me&to=you&body=stackoverflow
Sidenote:
If you want that info send from the client, you should use getParameter() calls instead.
test something like :
http://localhost:8080/someURL?att1=value1&att2=value2&att3=value3
It will show you the value1, value2 and value3 passed into the URL...

How to login with #RestController and send the object to angularjs

I have some trouble figuring out how to create a login form in angularjs using springboot.
I can register a user and send the data to the database but the problems begin when i want to login.
in angularjs i have a function like this
function Login(username, password, callback) {
$http.post('/api/authenticate', { username: username, password: password })
.success(function (response) {
callback(response);
});
}
What i managed to do but probably is't right:
#RequestMapping(value = "/authenticate/{id}",method = RequestMethod.GET)
public User getUser(#PathVariable Integer id) {
return repo.findOne(id);
}
This gives me following json
{"id":2,"username":"jdoe","password":"$2a$10$5hgIyQr.K9wb8cXEyWGbROAU.rkYzd19vP7ajHpwp1KUYdShfcPn.","lastname":"doe","firstname":"john","customfield":"Hello there"}
But now i have following problems and questions :
How can i check if the username and password is equal to the username and password of json by going to api/authenticate ? (without {id})
can i hide this json from the users ?
Is this safe ?
how will angular now all the users propertys ? (i suggest i can retrieve this from the json)
any pro tips on how to solve this?
From AngularJS you are calling HTTP POST method and at Spring side you have declared as HTTP GET, which is wrong.
Correct request mapping is
#RequestMapping(value = "/api/authenticate",method = RequestMethod.POST, consumes = "application/json")
#ResponseBody
public User getUser(#RequestBody User user) {
//here request body contains User POJO object's payload (JSON object)
//You are getting username from JSON,
//so you need to update your call to findOne method
return repo.findOne(user.getUserName());
}
Please refer
#RequestBody and #ReponseBody spring
#RequestBody annotation spring docs
#RequestMapping#consumes

Spring MVC redirection is adding some parameters in the url

I have a spring mvc web application with the following code. When the user is not logged in I am sending one tiles view.
And when the user is logged in I am redirecting to specific url patterns.
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String login() throws IOException {
if (logger.isDebugEnabled()) {
logger.debug("Requested with /login mapping");
}
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (!(authentication instanceof AnonymousAuthenticationToken)) {
List<String> userRoles = AuthenticationUtils.getUserRoles();
if (userRoles.contains("ROLE_ADMIN")) {
return "redirect:/admin.html";
} else if (userRoles.contains("ROLE_USER")) {
return "redirect:/user.html";
}
}
return "template";
}
I am getting the redirection but with some unexpected parameters. How to remove them?
http://localhost:8081/app/admin.html?total=48&loggedInUserRoles=207
I have tried the following url without success.
Spring MVC Controller: Redirect without parameters being added to my url
I have no clue of which part of code is adding the parameters.
You can make your method return View instead of String and then create RedirectView in a way:
RedirectView view = new RedirectView(url);
view.setExposeModelAttributes(false);
return view;

Categories