Spring Security Get logged user by session id - java

Recently I am trying to get existing logged user by JSESSIONID with Spring Security. After tracing the source code I still cannot find the way to do this. Is it possible? Where Spring Security store the mapping between JSESSIONID and AuthUser?
Any help will be very appreciated.

Something like this:
#RequestMapping(value = "/userAndSession/{providedSessionId}", method = RequestMethod.GET)
public String getUserAndSessionId(UsernamePasswordAuthenticationToken principal,
HttpServletRequest httpServletRequest, #PathVariable("providedSessionId") String sessionID) {
// Session ID
String sessionId = httpServletRequest.getRequestedSessionId();
if(sessionId.equals(providedSessionId)) {
// Username
String name = principal.getName();
}
}

Related

How to update user data in Principal when changing his login?

I made a page with editing user information, where it is possible to change the login. When I change it and return to the user profile, I get an error that Account is null.
Found out the reason. When changing the login, Principal's username remains the same as it was before the login change. I can't figure out how you can update Principal's username without logging out.
My AccountController:
#GetMapping("/settings")
public String showAccountSettings(Principal principal, Model model) {
Account account = accountRepository.findByLogin(principal.getName());
model.addAttribute("account", account);
return "settings";
}
#PostMapping("/settings/apply")
public String applyChangesInAccount(Principal principal, Account account) {
Account updAccount = accountRepository.findByLogin(principal.getName());
updAccount.getAccountInfo().setEmail(account.getAccountInfo().getEmail());
updAccount.getAccountInfo().setPhone(account.getAccountInfo().getPhone());
updAccount.setLogin(account.getLogin());
accountRepository.save(updAccount);
return "redirect:/";
}
Assuming you are using spring security,
Post your sucessful backend db calls,
You can do this with,
SecurityContextHolder.getContext().setAuthentication(newAuth);
Refer: https://stackoverflow.com/a/30674697/1811348

Problem getting the userName from jwtToken

I implemented security for my application using JWT tokens. I make a post request to the /auth endpoint (passing userName and password) and get back a token, which I then use for further requests to the other endpoints. Everything works perfectly fine, but I can't get the userName out of this token. Here' my controller method:
#GetMapping(produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
public ResponseEntity<List<SongList>> getSongListsForUser(#RequestParam("userId") String ownerId) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String userId = auth.getName();
return ResponseEntity.ok(userId.equals(ownerId)
? songListDAO.findListsOf(userId)
: songListDAO.findPublicListsOf(ownerId));
}
Found this solution here on stackoverflow.
I put a breakpoint at the line of the return statement to inspect whats inside the userId and got this:
Why this is not working? What do I have to do to get the userName (=userId) from the jwt token?

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

Create OAuth Flow for Twitter and Facebook with spring social

I need to transport certain data from one request to another for the oauth workflow.
#RequestMapping(value = "/connect/twitter", method = RequestMethod.POST)
public RedirectView connectTwitter(HttpServletRequest request,
Model model) {
TwitterConnectionFactory connectionFactory = new TwitterConnectionFactory(
environment.getProperty("spring.social.twitter.app-id"),
environment.getProperty("spring.social.twitter.app-secret"));
OAuth1Operations oauthOperations = connectionFactory.getOAuthOperations();
OAuthToken requestToken = oauthOperations.fetchRequestToken(request.getRequestURL().toString(), null);
String authorizeUrl = oauthOperations.buildAuthorizeUrl(requestToken.getValue(), OAuth1Parameters.NONE);
//need requestToken in the next process
return new RedirectView(authorizeUrl);
}
#RequestMapping(value = "/connect/twitter", method = RequestMethod.GET)
#ResponseBody
public String verifyTwitter(#RequestParam("oauth_token") String oauthToken,
#RequestParam("oauth_verifier") String oauthVerifier,
OAuthToken requestToken /*need requestToken from last request*/) {
TwitterConnectionFactory connectionFactory = new TwitterConnectionFactory(
environment.getProperty("spring.social.twitter.app-id"),
environment.getProperty("spring.social.twitter.app-secret"));
OAuth1Operations oauthOperations = connectionFactory.getOAuthOperations();
OAuthToken accessToken = oauthOperations.exchangeForAccessToken(new AuthorizedRequestToken(requestToken, oauthVerifier), null);
Connection<Twitter> twitterConnection = connectionFactory.createConnection(accessToken);
return "asd";
}
the requestToken from the frist request has to be available in the next request. how to handle it?
Well, one way to do it is to store it in "session". I say put quotes around that because I don't necessarily mean servlet session (which may or may not work across multiple nodes, depending on your server setup). It could be anything that performs the function of session, such as (perhaps) a Redis key-value store. Of course, once you fetch it from "session", you'll also want to clean it out.
Spring MVC supports flash attributes directly for this purpose. See http://docs.spring.io/spring/docs/4.0.6.RELEASE/spring-framework-reference/htmlsingle/#mvc-flash-attributes.
Also, it strikes me that you're writing your own controller to do the OAuth dance with Twitter, but Spring Social's ConnectController already exists for that purpose. See https://github.com/spring-projects/spring-social-samples/tree/master/spring-social-showcase for an example of how ConnectController is used.

How can I save information for current user in Spring & Hibernate?

I have a User table and a UserInfo table which keeps the personal information of the user. What I am trying to do is adding personel information after log in. There is OneToOne relationship between tables with userId column so I defined it like this :
UserInfo class :
public class UserInfo {
//...
#OneToOne
#JoinColumn(name="user_id")
private User user;
// ...
}
User class :
public class User implements UserDetails {
// ...
#OneToOne(mappedBy="user", cascade = CascadeType.ALL, fetch=FetchType.LAZY,optional=true)
private UserInfo userInfo;
...
}
After I log in, I want to add some user information to the db for current user. But I don't know how can i save user information in controller? Should I save User object like below? I've searched about it and there is a way to get current user's information:
(User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
But when I try to use it in the controller it just returns null. How can I do such operations (adding pers. info) for logged in user?
#RequestMapping(value = "/show", method = RequestMethod.POST)
public ModelAndView newUser(ModelMap model, Principal principal) {
ModelAndView result = new ModelAndView("home");
User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
UserInfo userinfo = new UserInfo();
userinfo.setPlacesVisit(userinfo.getPlacesVisit());
user.setUserInfo(userinfo);
userService.save(user);
String message = "Userinfo was successfully added.";
result.addObject("message", message);
return result;
}
instead of saving current object update current object. First get current user object in controller after that set UserInfo then update user object in database.
#RequestMapping(value = "/show", method = RequestMethod.POST)
public ModelAndView newUser(ModelMap model, Principal principal) {
String userName=principal.getName(); // username or email using user login
User user=userService.getUserByName(userName); // retrieve current user information
UserInfo userinfo = new UserInfo(); // create userinfor object
userinfo.setPlacesVisit(userinfo.getPlacesVisit());
user.setUserInfo(userinfo); // set userinfo to user
userService.update(user); // update user
String message = "Userinfo was successfully added.";
result.addObject("message", message);
return result;
}
You can retrieve to user with the Principal parameter :
public ModelAndView newUser(ModelMap model, Principal principal) {
User activeUser = (User) ((Authentication) principal).getPrincipal();
}
SecurityContextHolder is a part of Spring Security. If you want to use this component, you have to set up Spring Security for the log in of your application to be able to retrieve, in your REST controller, the current user (javax.security.Principal)
Spring Security Documentation
You can use session to save session attributes. In spring, you can access session using
ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
HttpSession session = attr.getRequest().getSession();
You can save your logged user in session:
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
request.getSession().setAttribute("key", user);
and if you want get currently logged user, just:
(User) user = ((HttpServletRequest) request).getSession().getAttribute("key")
This example is in JSF, but I am sure that is also possible without JSF

Categories