Hello so i have this method in JwtUtill
public Boolean validateToken(String token, UserDetails userDetails) {
final String username = extractEmail(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}
But how can i request UserDetails in controller?
#GetMapping("/validateToken")
public String validateToken(#RequestHeader(value="token") String token) {
if(jwtUtil.validateToken(token,???)) {
}
}
Angular side
public isTokenExpired(): Observable<string> {
const headers = new HttpHeaders().set('token', localStorage.getItem('token'));
return this.httpClient.get<string>('http://localhost:8080/api/validateToken', {headers, responseType: 'text' as 'json'});
}
Also as frontend im using angular
You can simply inject it using #AuthenticationPrincipal. Eg:
#GetMapping("/validateToken")
public String validateToken(#AuthenticationPrincipal UserDetails userDetails, ...
It seems like you are using jwt, you don't need UserDetails to compare it with.
change methods as :
public Boolean validateToken(String token) {
final String username = extractEmail(token);
return (!StringUtils.isEmpty(username) && !isTokenExpired(token));
}
#GetMapping("/validateToken")
public String validateToken(#RequestHeader(value="token") String token) {
if(jwtUtil.validateToken(token)) {
}
}
If your token is invalid you will not get exception in extractEmail method and if it is expired then method isTokenExpired will return false.
UserDetails comes in the security context in the principal
UserDetails userDetails =
(UserDetails)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
Related
I have an application which was working with (email/password) login process.
Now i have implemented LDAP auth.
A user enter in the authenticate process, if the database doesn't know him, it comes in the ldap process, and if it works, then we create his account in the database.
Next we receive the JWT token.
The problem is that if we retry to connect, new UsernamePasswordAuthenticationToken(email, password); is returning authenticated false. But credentials are OK, it should works...
I don't understand what is happening.. user is shown in the database with the password encrypted..
#Service
#RequiredArgsConstructor
public class OpenLdapAuthenticationProvider implements AuthenticationProvider {
#Value("${spring.ldap.enabled}")
private Boolean enableLDAP;
#Autowired
private LdapTemplate ldapTemplate;
private final UserService userService;
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String email = authentication.getName();
String password = authentication.getCredentials().toString();
// This method returns authenticated false !
Authentication authenticationWithDatabase = this.tryAuthWithDatabase(email, password);
if (authenticationWithDatabase.isAuthenticated() == false) {
if (enableLDAP == true) {
boolean authenticationWithLdap = this.tryAuthWithLdap(email, password);
if (authenticationWithLdap == true) {
UserDataDTO userDataDTO = this.retrieveUserInformationFromLDAP(email);
userDataDTO.setEmail(email);
userDataDTO.setPassword(password);
List<AppUserRole> userRoles = new ArrayList<>();
userRoles.add(AppUserRole.ROLE_DEV_VIEW);
userDataDTO.setAppUserRoles(userRoles);
boolean trySignup = userService.signup(userDataDTO);
if (trySignup == true) {
return this.tryAuthWithDatabase(email, password);
} else {
throw new InternalServerErrorException("Your account is not in database. Sign in with LDAP was OK, but registration failed. This should not happen.");
}
} else {
throw new UnAuthorizedErrorException(
"The connection has been refused (by the database and ldap). Check your credentials.");
}
} else {
throw new UnAuthorizedErrorException(
"The connection has been refused by the database and cannot be made by ldap because it has been disabled.");
}
} else {
return authenticationWithDatabase;
}
}
private Authentication tryAuthWithDatabase(String email, String password) {
return new UsernamePasswordAuthenticationToken(email, password);
}
private boolean tryAuthWithLdap(String email, String password) {
Filter filter = new EqualsFilter("mail", email); // mail = le champs dans l'arbre LDAP
return ldapTemplate.authenticate(LdapUtils.emptyLdapName(), filter.encode(), password);
}
public UserDataDTO retrieveUserInformationFromLDAP(String email) {
LdapQuery query = LdapQueryBuilder.query().where("objectClass").is("user").and("mail").is(email);
return ldapTemplate.search(query,
(AttributesMapper<UserDataDTO>) attributes ->
UserDataDTO.builder()
.name(attributes.get("givenName").get().toString())
.surname(attributes.get("sn").get().toString())
.username(attributes.get("displayName").get().toString())
.team(attributes.get("department").get().toString())
.build()).get(0);
}
#Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
#RequiredArgsConstructor
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private JwtTokenProvider jwtTokenProvider;
#Autowired
private OpenLdapAuthenticationProvider openLdapAuthenticationProvider;
public WebSecurityConfig(JwtTokenProvider jwtTokenProvider) {
this.jwtTokenProvider = jwtTokenProvider;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(this.openLdapAuthenticationProvider);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(corsFilter(), ChannelProcessingFilter.class);
http.csrf().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.authorizeRequests()
.antMatchers("/api/v3/authentificate").permitAll()
.antMatchers("/api/v3/signup").permitAll()
.anyRequest().authenticated();
http.apply(new JwtTokenFilterConfigurer(jwtTokenProvider));
}
#Override
public void configure(WebSecurity web) throws Exception {
// Allow swagger to be accessed without authentication
web.ignoring().antMatchers("/v3/api-docs/**")//
.antMatchers("/swagger-resources/**")//
.antMatchers("/swagger-ui/**")
.antMatchers("/swagger-ui.html");
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
#Configuration
public class GenericBeanConfig {
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12);
}
#Bean
public ModelMapper modelMapper() {
return new ModelMapper();
}
}
Thanks for any help, i really don't understand what's happening..
If you check UsernamePasswordAuthenticationToken.class, you will see 2 constructors:
/**
* This constructor can be safely used by any code that wishes to create a
* <code>UsernamePasswordAuthenticationToken</code>, as the {#link #isAuthenticated()}
* will return <code>false</code>.
*
*/
public UsernamePasswordAuthenticationToken(Object principal, Object credentials) {
super(null);
this.principal = principal;
this.credentials = credentials;
setAuthenticated(false);
}
/**
* This constructor should only be used by <code>AuthenticationManager</code> or
* <code>AuthenticationProvider</code> implementations that are satisfied with
* producing a trusted (i.e. {#link #isAuthenticated()} = <code>true</code>)
* authentication token.
* #param principal
* #param credentials
* #param authorities
*/
public UsernamePasswordAuthenticationToken(Object principal, Object credentials,
Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;
this.credentials = credentials;
super.setAuthenticated(true); // must use super, as we override
}
The same can be seen in its documentation
Spring security's default implementation expects you to provide at least one granted authority to your user instance
That happens because Authentication provider receives an Authentication object not authenticated as input only username and password, by applying its logic (fetching from database, etc) if the result matches it returns an Authentication object username, password and its authorities if it doesnt match it returns that same input object
To solve your problem, you can try the following purely illustrative code:
// omitted code above
private Authentication tryAuthWithDatabase(String email, String password) {
// call your database or repository or service
// var fetchData receives the object from database
// perform token the matching against the fetch data
if( resultMatches ) {
return new UsernamePasswordAuthenticationToken(email, password, fetchData.getAuthorities() );
}
else {
return new UsernamePasswordAuthenticationToken( email, password );
}
}
// omitted code bellow
I hope i´ve helped. Let me know if you made it. Cheers!
I have spent days on trying to get ROLES working within Spring Security using JWT tokens. Authentication seems to work fine but authorization seems to still not be working.
My current setup is that I have...
an In Memory Database for Users (I have one single user called "lion", and one single role "KING")
an authenticate end point which authenticates the user, and returns the JWT in the response.
My WebCofig looks like this :
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/hello").permitAll()
.antMatchers("/authenticate").permitAll()
.anyRequest().authenticated()
.and().exceptionHandling()
.and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
I Basically want to say
anyone can access (/)
anyone can access "hello" and "authenticate"
My web controller looks like this :
#Controller
public class WebController {
#PreAuthorize("permitAll()")
#RequestMapping("/hello")
#ResponseBody
public String hello() {
return "Hello! ALL USERS logged in or not are allowed to see this!";
}
#PreAuthorize("hasRole('KING')")
#RequestMapping("/king")
#ResponseBody
public String king() {
return "Hello King";
}
#PreAuthorize("hasRole('ROLE_KING')")
#RequestMapping("/king2")
#ResponseBody
public String king2() {
return "Hello King2";
}
}
My web token returned via my authentication looks good (i think..). Decoded the body looks like this :
{
"sub": "lion",
"scopes": "KING",
"iat": 1580645802,
"exp": 1580663802
}
... and will allow me to access anywhere where I just need to be authenticated. "anyRequest().authenticated()".
However both king and king2 REST endpoints give me 403 - "Access Denied" even though my user has role KING (I tried both KING and ROLE_KING)
I feel like I am missing a piece of the puzzle.
My JWT Filter seems to look good too. The authentication object (..which is set in the security context handler like so : SecurityContextHolder.getContext().setAuthentication(authentication);) has exactly ONE SimpleGrantedAuthority with role = KING.
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
final String authorizationHeader = request.getHeader("Authorization");
String username = null;
String jwt = null;
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
jwt = authorizationHeader.substring(7);
username = jwtUtil.extractUsername(jwt);
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (jwtUtil.validateToken(jwt, userDetails)) {
userDetails.getAuthorities(); //has exactly ONE SimpleGrantedAuthority with value "KING"
SimpleGrantedAuthority s = new SimpleGrantedAuthority("asfd");
s.getAuthority(); //string
UsernamePasswordAuthenticationToken authentication = jwtUtil.getAuthentication(jwt,
SecurityContextHolder.getContext().getAuthentication(), userDetails);
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
logger.info("authenticated user " + username + ", setting security context");
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
chain.doFilter(request, response);
}
My UserDetailsService looks like this :
public class UserService implements UserDetailsService {
#Autowired
private UserRepository repository;
#Autowired
private PasswordValidationService passwordValidationService;
#Override
public User loadUserByUsername(String userName) throws UsernameNotFoundException {
UserEntity u = repository.findByUserNameIgnoreCase(userName);
SimpleGrantedAuthority a = new SimpleGrantedAuthority(u.getRole().toString());
ArrayList<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
auths.add(a);
return new User(u.getUserName(), u.getPassword(), auths);
}
}
Everything looks good to me which is why I am confused right now :(
*********** UPDATE ************
If I use hasAuthority instead of hasRole then this works :
#PreAuthorize("hasAuthority('KING')")
#RequestMapping("/king3")
#ResponseBody
public String king3() {
return "Hello King";
}
So how do I get hasRole to work? Am I missing the appending of "ROLE_" somewhere in my code?
I am new to groovy and spring boot.I start to work on login with spring boot.
I need to pass two additional parameters to the CustomAuthToken class.
I can pass only one.When I assign other variable to some value auth fail.
This is my code.
CustomAuthFilter.groovy
Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (!request.post) {
throw new AuthenticationServiceException("not supported: $request.method")
}
String username = (obtainUsername(request) ?: '').trim()
String password = (obtainPassword(request) ?: '').trim()
String extrafield1 = request.getParameter("extrafield1")
String extrafield2 = request.getParameter("extrafield2")
def authentication = new CustomAuthToken(username, password, extrafield1, null, false, false, false)
HttpSession session = request.getSession(false)
if (session || getAllowSessionCreation()) {
request.session['SPRING_SECURITY_LAST_USERNAME_KEY'] = TextEscapeUtils.escapeEntities(username)
}
return getAuthenticationManager().authenticate(authentication)
}
CustomAuthToken.groovy
CustomAuthToken(Object principal, Object credentials, String extrafield1, String PVM, Boolean isAccept, Boolean isLogEnabled, Boolean is3PLEnabled) {
super(principal, credentials)
extra1 = extrafield1
}
It is working and I can access the extra1 field.
But when I try to pass anther parameter it's not working.
CustomAuthToken(Object principal, Object credentials, String extrafield1, String extrafield2, String PVM, Boolean isAccept, Boolean isLogEnabled, Boolean is3PLEnabled) {
super(principal, credentials)
extra1 = extrafield1
extra2 = extrafield2
}
When I try this extra2 is passing. But auth is fail.
Can anyone have an idea about this?
My guess is that
CustomAuthToken extends UsernamePasswordAuthenticationToken
If that's the case, you need to change the super constructor call from
super(principal, credentials)
to
super(principal, credentials, Collections.emptyList())
You see, the constructor you are invoking sets authenticated=false
public UsernamePasswordAuthenticationToken(Object principal, Object credentials) {
super(null);
this.principal = principal;
this.credentials = credentials;
setAuthenticated(false);
}
So you want to invoke the correct constructor
public UsernamePasswordAuthenticationToken(Object principal, Object credentials,
Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;
this.credentials = credentials;
super.setAuthenticated(true); // must use super, as we override
}
Using Dropwizard 1.2.0 and Dropwizard JWT library, I am trying to create json web tokens from an API endpoint called /token
This endpoint requires the client to pass a username and password, using Basic Authentication method. If successful the response will contain a JSON web token.
Principal
public class ShepherdAuth implements JwtCookiePrincipal {
private String name;
private Set<String> roles;
public ShepherdAuth(String name, Set<String> roles) {
this.name = checkNotNull(name, "User name is required");
this.roles = checkNotNull(roles, "Roles are required");
}
#Override
public boolean isPersistent() {
return false;
}
#Override
public boolean isInRole(final String s) {
return false;
}
#Override
public String getName() {
return this.name;
}
#Override
public boolean implies(Subject subject) {
return false;
}
public Set<String> getRoles() {
return roles;
}
}
Authenticator
public class ShepherdAuthenticator implements Authenticator<BasicCredentials, ShepherdAuth> {
private static final Map<String, Set<String>> VALID_USERS = ImmutableMap.of(
"guest", ImmutableSet.of(),
"shepherd", ImmutableSet.of("SHEPHERD"),
"admin", ImmutableSet.of("ADMIN", "SHEPHERD")
);
#Override
public Optional<ShepherdAuth> authenticate(BasicCredentials credentials) throws AuthenticationException {
if (VALID_USERS.containsKey(credentials.getUsername()) && "password".equals(credentials.getPassword())) {
return Optional.of(new ShepherdAuth(credentials.getUsername(), VALID_USERS.get(credentials.getUsername())));
}
return Optional.empty();
}
}
Resource / Controller
public class ShepherdController implements ShepherdApi {
public ShepherdController() {
}
#PermitAll
#GET
#Path("/token")
public ShepherdAuth auth(#Auth final BasicCredentials user) {
return new ShepherdAuth(user.getUsername(),
ImmutableSet.of("SHEPHERD"));
}
App / Config
#Override
public void run(final ShepherdServiceConfiguration configuration,
final Environment environment) {
final ShepherdController shepherdController = new ShepherdController();
// app authentication
environment.jersey().register(new AuthDynamicFeature(new BasicCredentialAuthFilter.Builder<ShepherdAuth>()
.setAuthenticator(new ShepherdAuthenticator())
.setAuthorizer(new ShepherdAuthorizer())
.setRealm(configuration.getName())
.buildAuthFilter()));
When I try to make a request to /shepherd/token I do not get a prompt for basic auth, instead I get a HTTP 401 response with
Credentials are required to access this resource.
How do I get the controller to prompt for username and password and generate a JWT on success?
I implemented JWT tokens in my project by using https://github.com/jwtk/jjwt but the solution will easily be applied to another library. The trick is to use different authenticators.
This answer is not suited for Dropwizard JWT Library but does the fine job of providing JWT for Dropwizard :)
First, the application:
environment.jersey().register(new TokenResource(configuration.getJwsSecretKey()));
environment.jersey().register(new HelloResource());
environment.jersey().register(RolesAllowedDynamicFeature.class);
environment.jersey().register(new AuthValueFactoryProvider.Binder<>(User.class));
environment.jersey()
.register(
new AuthDynamicFeature(
new ChainedAuthFilter<>(
Arrays
.asList(
new JWTCredentialAuthFilter.Builder<User>()
.setAuthenticator(
new JWTAuthenticator(configuration.getJwsSecretKey()))
.setPrefix("Bearer").setAuthorizer(new UserAuthorizer())
.buildAuthFilter(),
new JWTDefaultCredentialAuthFilter.Builder<User>()
.setAuthenticator(new JWTDefaultAuthenticator())
.setAuthorizer(new UserAuthorizer()).setRealm("SUPER SECRET STUFF")
.buildAuthFilter()))));
Please note that the configuration class must contain a configuration setting:
String jwsSecretKey;
Here, the TokenResource is the token supplying resource, and the HelloResource is our test resource. User is the principal, like this:
public class User implements Principal {
private String name;
private String password;
...
}
And there is one class for communicating the JWT token:
public class JWTCredentials {
private String jwtToken;
...
}
TokenResource provides tokens for a user "test" with password "test":
#POST
#Path("{user}")
#PermitAll
public String createToken(#PathParam("user") String user, String password) {
if ("test".equals(user) && "test".equals(password)) {
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(this.secretKey);
Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
JwtBuilder builder = Jwts.builder().setIssuedAt(now).setSubject("test")
.signWith(signatureAlgorithm, signingKey);
return builder.compact();
}
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
}
And the HelloResource just echoes back the user:
#GET
#RolesAllowed({"ANY"})
public String hello(#Auth User user) {
return "hello user \"" + user.getName() + "\"";
}
JWTCredentialAuthFilter provides credentials for both authentication schemes:
#Priority(Priorities.AUTHENTICATION)
public class JWTCredentialAuthFilter<P extends Principal> extends AuthFilter<JWTCredentials, P> {
public static class Builder<P extends Principal>
extends AuthFilterBuilder<JWTCredentials, P, JWTCredentialAuthFilter<P>> {
#Override
protected JWTCredentialAuthFilter<P> newInstance() {
return new JWTCredentialAuthFilter<>();
}
}
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
final JWTCredentials credentials =
getCredentials(requestContext.getHeaders().getFirst(HttpHeaders.AUTHORIZATION));
if (!authenticate(requestContext, credentials, "JWT")) {
throw new WebApplicationException(
this.unauthorizedHandler.buildResponse(this.prefix, this.realm));
}
}
private static JWTCredentials getCredentials(String authLine) {
if (authLine != null && authLine.startsWith("Bearer ")) {
JWTCredentials result = new JWTCredentials();
result.setJwtToken(authLine.substring(7));
return result;
}
return null;
}
}
JWTAuthenticator is when JWT credentials are provided:
public class JWTAuthenticator implements Authenticator<JWTCredentials, User> {
private String secret;
public JWTAuthenticator(String jwtsecret) {
this.secret = jwtsecret;
}
#Override
public Optional<User> authenticate(JWTCredentials credentials) throws AuthenticationException {
try {
Claims claims = Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(this.secret))
.parseClaimsJws(credentials.getJwtToken()).getBody();
User user = new User();
user.setName(claims.getSubject());
return Optional.ofNullable(user);
} catch (#SuppressWarnings("unused") ExpiredJwtException | UnsupportedJwtException
| MalformedJwtException | SignatureException | IllegalArgumentException e) {
return Optional.empty();
}
}
}
JWTDefaultAuthenticator is when no credentials are present, giving the code an empty user:
public class JWTDefaultAuthenticator implements Authenticator<JWTCredentials, User> {
#Override
public Optional<User> authenticate(JWTCredentials credentials) throws AuthenticationException {
return Optional.of(new User());
}
}
UserAuthorizer permits the "ANY" role, as long as the user is not null:
public class UserAuthorizer implements Authorizer<User> {
#Override
public boolean authorize(User user, String role) {
return user != null && "ANY".equals(role)
}
}
If all goes well,
curl -s -X POST -d 'test' http://localhost:8080/token/test
will give you something like:
eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1MDk3MDYwMjYsInN1YiI6InRlc3QifQ.ZrRmWTUDpaA6JlU4ysIcFllxtqvUS2OPbCMJgyou_tY
and this query
curl -s -X POST -d 'xtest' http://localhost:8080/token/test
will fail with
{"code":401,"message":"HTTP 401 Unauthorized"}
(BTW, "test" in the URL is the user name and "test" in the post data is the password. As easy as basic auth, and can be configured for CORS.)
and the request
curl -s -X GET -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1MDk3MDYwMjYsInN1YiI6InRlc3QifQ.ZrRmWTUDpaA6JlU4ysIcFllxtqvUS2OPbCMJgyou_tY' http://localhost:8080/hello
will show
hello user "test"
while
curl -s -X GET -H 'Authorization: Bearer invalid' http://localhost:8080/hello
and
curl -s -X GET http://localhost:8080/hello
will result in
{"code":403,"message":"User not authorized."}
Your missing this line in your configuration.
environment.jersey().register(new AuthValueFactoryProvider.Binder<>(User.class));
I have an spring mvc web application in which users login to session "session.setAttribute" classically. Whenever I need loggedin user data I use this data.
Now I want to add android app and what I want to learn do I have to add additional methods for each android request and send user data within it?
Or Is there away to make a request to same methods.
What is the consept for this kind of cloud apps? Do I have to write different methods for android requests? Because it is not possible session.getAttribute when wemake an android request, it returns null.
User user = userService.getByUserNameAndPassword(userName, password);
if (user != null) {
if (user.isActive()) {
Account account = new Account(user, request.getRemoteAddr());
HttpSession httpSession = request.getSession(true);
AccountRegistry.add(httpSession);
httpSession.setAttribute(Constant.ACCOUNT, account);
result.put(Constant.REF, Constant.SUCCESS);
}
public class Account {
private UserRightsHandler userRightsService = null;
private User user;
private String ipAddress;
private boolean admin;
public Account(User user, String ipAddress) {
this.user = user;
this.ipAddress = ipAddress;
userRightsService = new UserRightsHandler(user);
setAdmin(userRightsService.isAdmin());
}
public UserRightsHandler getUserRightsService() {
return userRightsService;
}
public User getUser() {
return this.user;
}
public String getIpAddress() {
return ipAddress;
}
public boolean isAdmin() {
return admin;
}
private void setAdmin(boolean admin) {
this.admin = admin;
}
}
public class AccountRegistry {
private static final Map<String, HttpSession> sessions = new HashMap<String, HttpSession>();
public static void add(HttpSession session) {
sessions.put(session.getId(), session);
}
public static void remove(HttpSession session) {
if (session != null) {
sessions.remove(session.getId());
session.setAttribute(Constant.ACCOUNT, null);
session.invalidate();
}
}
public static HttpSession getByHttpSessionID(String httpSessionID) {
Set<String> keys = sessions.keySet();
Iterator it = keys.iterator();
while (it.hasNext()) {
String sID = (String) it.next();
HttpSession session = sessions.get(sID);
if (sID.equals(httpSessionID)) {
return session;
}
}
return null;
}
public static void removeByHttpSessionID(String httpSessionID) {
HttpSession session = getByHttpSessionID(httpSessionID);
remove(session);
}
public static Account getCurrentAccount() {
HttpServletRequest request = ContextFilter.getCurrentInstance().getRequest();
HttpSession session = request.getSession();
return (Account) session.getAttribute(Constant.ACCOUNT);
}
}
#RequestMapping(value = "/changeStatus", method = RequestMethod.POST)
public #ResponseBody
String changeStatus(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
User editor = AccountRegistry.getCurrentAccount().getUser();
}
You can ask user send their user and password at the start of Android app via custom authenticate request like /appLogin then if it is correct creditentals you can return a key to user (to app) and store it to some variable during app run. Then when user want to do something send a request to server you can send it to a function with mapping like /appExampleService then you can check at that function this key and device valid depending on how you handle custom login process then this function call existing function that is used for web browsers that have mapping /exampleService. For example;
#JsonSerialize
#RequestMapping("/appExampleService")
public int someServiceForAppClient(
#RequestParam(value = "key", required = true) String apikey,
#RequestParam(value = "param", required = true) String someParam{
String name=userDAO.getUsernameFromApiKey(apikey);
return someService(someParam, name);
}
#JsonSerialize
#RequestMapping("/exampleService")
public int someServiceForWebClient(
#RequestParam(value = "param", required = true) String someParam) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String name = auth.getName();
return someService(someParam, name);
}
public int someService(String someParam,String name){
return doBusiness(someParam, name);
}
userDAO is just something I created for to get info of user with given key. And there is a service for App login as well which return that key to user when he started the app send his username and pass