Login and get information user with token in spring (no OAuth) - spring

I am implementing a project RESTful API, it should login (username / password) and returns a token, I want to use token to retrieve user information.
I follow the instructions:
https://github.com/virgo47/restful-spring-security
But: I do not know how to use it in my function, you can help me with?
#RequestMapping(value = "/login", method = RequestMethod.POST)
public #ResponseBody ResponseObject<Object> login(
#RequestParam(value = "username", required = true) String username,
#RequestParam(value = "password", required = true) String password,
#RequestHeader(value = "token") String token,
HttpSession session) {
//TODO
return new ResponseObject<Object>(1, "Success", data);
}
#RequestMapping(value = "/info", method = RequestMethod.GET)
public #ResponseBody ResponseObject<User> getInfo(#RequestHeader(value = "token", required = true) String token,
HttpSession session) {
//TODO
return null;
}

Why would you want to do that ? Why not just get the logged in user from the SecurityContext as follows
#RequestMapping(value = "/test", method = RequestMethod.GET)
public String test() {
System.out.println(" *** MainRestController.test");
// Spring Security dependency is unwanted in controller, typically some
// #Component (UserContext) hides it.
// Not that we don't use Spring Security annotations anyway...
return "SecurityContext: "
+ SecurityContextHolder.getContext().getAuthentication()
.getName();
}
If you insist on doing it, you can do the following.
UserDetails userDetails =
(UserDetails)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
tokenManager.getUserTokens(userDetails)

Related

How to get the username (email in my case) in Spring Security [UserDetails/String]

I would like to get the e-mail which is username in my application to set the user which send a message. I decided to use typical method i.e. principal and getUsername():
#PostMapping("/messages/{id}")
#ResponseStatus(HttpStatus.CREATED)
public MessageDTO addOneMessage(#RequestBody MessageRequest messageRequest, #PathVariable ("id") Long id) {
checkIfChannelExists(id);
String content = messageRequest.getContent();
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username = ((UserDetails) principal).getUsername();
Employee author = employeeRepository.findByEmail(username).get();
Message message = new Message(content, author, id);
messageRepository.save(message);
return new MessageDTO(message);
}
And MessageRequest.java:
#Data
#NoArgsConstructor
#AllArgsConstructor
public class MessageRequest {
#NonNull
private String content;
}
But, in this way I still get:
"message": "java.lang.String cannot be cast to org.springframework.security.core.userdetails.UserDetails"
What is wrong in my implementation? To be more precise, I use Postman to test POST requests:
{
"content": "something"
}
If you only need to retrieve the username you can get it through Authentication ie.
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String username = authentication.getName();
instead of typecasting to your class springcontext provide the almost all details about the user.
If you want the controller to get the user name to test.
please use this code.
//using authentication
#RequestMapping(value = "/name", method = RequestMethod.GET)
#ResponseBody
public String currentUserName(Authentication authentication) {
return authentication.name();
}
//using principal
#RequestMapping(value = "/name", method = RequestMethod.GET)
#ResponseBody
public String currentUserName(Principal principal) {
return principal.getName();
}

Request method 'POST' not supported in Springboot MVC

Below are my GET and POST methods..
When I run the application, I get this error: Request method 'POST' not supported.
GET Method:
#RequestMapping(value = "userProfiles/{userId}/setup/Tool", method = RequestMethod.GET)
public String ToolSetup(Model model, #PathVariable int userId, #RequestParam(value = "update", defaultValue = "false") boolean update) {
model.addAttribute("formInput", new Resource());
model.addAttribute("userId", userId);
if (update) {
model.addAttribute("update", "update");
} else model.addAttribute("update", "");
return "Tool";
}
Below is my POST method:
#RequestMapping(value = "/userProfiles/{userId}/setup/Tool", method = RequestMethod.POST)
#ResponseBody
public void makeVideo(#PathVariable Long userId, #ModelAttribute("formInput") Resource formInput,
Authentication authentication,
ModelMap modelMap,
#RequestParam("uploadingFiles") MultipartFile[] uploadingFiles,
#RequestParam("track_value") int trackNumber,
HttpServletResponse response) throws IOException, URISyntaxException, InterruptedException, FrameGrabber.Exception,FrameRecorder.Exception {
UserProfile userProfile = userProfileRepository.findOne(userId);
ArrayList<String> photos = new ArrayList<>();
String audioPath= audioPath1;
for(MultipartFile file : uploadingFiles){
photos.add(file.getName());
}
formInput.setUploadingFiles(photos);
modelMap.put("formInput", formInput);
//some processing with images and the audio
response.sendRedirect("/userProfiles/" + userId + "/Tool/Processing"); //redirect to notif. page, then redirect to logged in home
}
HTML:
<form th:action="#{${#httpServletRequest.requestURI + '?update=true'}}" th:object="${formInput}" method="POST" enctype="multipart/form-data">
I know there are other posts related to this once, and I have tried all the recommended solutions from them but nothing seems to work..
Any help is appreciated!

Redirect does not working properly using spring mvc

Redirection does not work properly. I could not understand the problem because I very new to spring.
Here is my controller when I submit my form then ("schoolform") submitForm controller called and it redirect to another controller to ('form') form controller but it goes to ("login") login controller. I don't know why ?
I want to redirect schoolform to form controller.
#RequestMapping(value = "/schoolform", method = RequestMethod.POST)
public String submitForm(#ModelAttribute("school")School school,Model model,HttpServletRequest request,HttpServletResponse resp) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
schoolService.update(school);
System.out.println("Form submitted finaly, No further changes can be made.");
return "redirect:/form.html";
}
#RequestMapping(value = "/form", method = RequestMethod.GET)
public String form(Model model,HttpServletRequest request) {
HttpSession session = request.getSession(true);
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String name = auth.getName(); // get logged in username
System.out.println(name+"--------form page-----");
}
#RequestMapping(value = "/login", method = RequestMethod.GET)
public ModelAndView login(
#RequestParam(value = "error", required = false) String error,
#RequestParam(value = "logout", required = false) String logout) {
logger.info("------------------LoginController ---------------");
System.out.println("LoginController ");
ModelAndView model = new ModelAndView();
if (error != null) {
model.addObject("error", "Invalid username and password!");
}
if (logout != null) {
model.addObject("msg", "You've been logged out successfully.");
}
model.setViewName("login");
return model;
}
I think it is not working because the method in which you are trying to redirect to a url, accepts POST requests. You cannot redirect from POST methods UNLESS you have a handler method that accepts GET method and whose #RequestMapping accepts the value where you are trying to redirect.
So basically, the method submitForm which accepts POST requests only, is trying to redirect to /form.html. Now, there is no method in your controller that accepts /form.html, So now you gotto have a method in your controller class whose mapping value is /form.html and it accepts GET requests:
#RequestMapping(value = "/form.html", method = RequestMethod.GET)
public String methodName(arg1 ..){ ... }

Spring MVC variable resets for no reason

For some reason when I execute a GET request to a certain URI the variable that I need to access in that method loses its memory or points to null.
I have a form where a user can update his personal information. But when he enters a duplicate, it redirects him to a page that lets him know
I have : private static volatile User currentUser;
This field is set when a user logs in and the server performs a GET request to a REST API, which I programmed myself, and returns the User containing his info. This works as expected and the user info is displayed on his home screen.
Code for the above:
#RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(#ModelAttribute Credentials credentials,
RedirectAttributes redirect) {
RestTemplate restTemplate = new RestTemplate();
RoleInfo roleInfo = restTemplate.postForObject(
"http://localhost:9090/users/login", credentials,
RoleInfo.class);
if (roleInfo != null) {
if (roleInfo.isAdmin()) {
redirect.addFlashAttribute("credentials", credentials);
return "redirect:/adminHome";
} else {
redirect.addFlashAttribute("credentials", credentials);
return "redirect:/getBasicUser";
}
} else {
return "login_fail";
}
}
#RequestMapping(value = "/getBasicUser", method = RequestMethod.GET)
public <T> String getBasicUser(#ModelAttribute Credentials credentials,
Model model, RedirectAttributes redirect) {
RestTemplate restTemplate = new RestTemplate();
String url = "http://localhost:9090/users/getBasicUser?username="
+ credentials.getUsername();
ResponseEntity<User> responseEntity = restTemplate.exchange(
url,
HttpMethod.GET,
new HttpEntity<T>(createHeaders(credentials.getUsername(),
credentials.getPassword())), User.class);
User user;
user = responseEntity.getBody();
currentUser = user;
System.out.println("current user: " + currentUser.getUsername());
if (user != null) {
userName = credentials.getUsername();
passWord = credentials.getPassword();
redirect.addFlashAttribute("credentials", credentials);
redirect.addFlashAttribute("user", user);
return "redirect:/basicHome";
} else {
return "register_fail";
}
}
So on "basicHome" he can view his information. Also on that page is a link to a form where he can edit the information:
#RequestMapping(value = "/edit", method = RequestMethod.GET)
public String getEditProfilePage(Model model) {
model.addAttribute("currentUser", currentUser);
System.out.println("current use firstname: " + currentUser.getFirstname());
model.addAttribute("user", new User());
return "edit_profile";
}
If an edit is successful he is returned back to his home page with the updated information.
The problem comes when he enters invalid info. He should be redirected back to the "/edit" URI and the currentUserfield should still hold his information but is actually null.
Here is the "/edit" PUT function:
#RequestMapping(value = "/edit", method = RequestMethod.PUT)
public <T> String editProfile(#ModelAttribute("user") User user,
#ModelAttribute("credentials") Credentials credentials,
RedirectAttributes redirect) {
RestTemplate restTemplate = new RestTemplate();
String url = "http://localhost:9090/users/update?username=" + userName;
HttpHeaders headers = createHeaders(userName,
passWord);
#SuppressWarnings({ "unchecked", "rawtypes" })
HttpEntity<T> entity = new HttpEntity(user, headers);
ResponseEntity<User> responseEntity = restTemplate.exchange(url,
HttpMethod.PUT, entity, User.class);
User returnedUser = responseEntity.getBody();
currentUser = returnedUser;
if (returnedUser != null) {
redirect.addFlashAttribute("user", returnedUser);
redirect.addFlashAttribute("credentials", credentials);
return "redirect:/basicHome";
} else {
return "redirect:/editFail";
}
}
I figured out what I had to do. I basically made "user" a session object in: #SessionAttributes("user")

How to use form validation and session in Spring MVC

This is my code:
#Controller
#RequestMapping("loginform.htm")
public class LoginController {
#RequestMapping(method = RequestMethod.GET)
public String showForm(Map<String, LoginForm> model) {
LoginForm loginForm = new LoginForm();
model.put("loginForm", loginForm);
return "loginform";
}
#RequestMapping(method = RequestMethod.POST)
public String processForm(#Valid LoginForm loginForm, BindingResult result,
Map<String, LoginForm> model) {
String userName = "UserName";
String password = "password";
if (result.hasErrors()) {
return "loginform";
}
loginForm = (LoginForm) model.get("loginForm");
if (!loginForm.getUserName().equals(userName)
|| !loginForm.getPassword().equals(password)) {
return "loginform";
}
model.put("loginForm", loginForm);
return "success";
}
}
I use this to validate form when user input username and password. But the question is when validate success, I want to add user information to session in this page. Please tell me how I can do that, I tried to add function
public ModelAndView handleRequest(HttpServletRequest request,HttpServletResponse response)
but it show nothing. Do you have any idea? Thanks!
In general: instead of implementing security stuff by your self you should use Spring Security.
To access sessions in Spring you have tree different ways:
Work with the Http Session direcly (add the parameter HttpSession session to your controller method)
#SessionAttributes - to access an specific field of you session
Attaches beans to the session (session scoped beans)

Resources