How to implement JWT based authentication and authorization in Spring Security
I am trying to implement jwt based authentication and authorization in my spring boot app. I followed a tutorial written here. But it does not do anything in my app. It does not return jwt token rather I am authenticated and my request is fulfilled. I am new to spring security. here is my code.
I want my app return jwt token and using the token the requests must be authorized.
Here is my code.
JWTAuthenticationFilter.java
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private AuthenticationManager authenticationManager;
#Autowired
CustomUserDetailsService userService;
public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
#Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
try {
CustomUserDetails user = new ObjectMapper().readValue(request.getInputStream(), CustomUserDetails.class);
return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), new ArrayList<>()));
} catch (Exception e) {
}
return super.attemptAuthentication(request, response);
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
Authentication auth) {
String loggedInUser = ((CustomUserDetails) auth.getPrincipal()).getUsername();
Claims claims = Jwts.claims().setSubject(loggedInUser);
if (loggedInUser != null) {
CustomUserDetails user = (CustomUserDetails) userService.loadUserByUsername(loggedInUser);
String roles[] = {};
for (Role role : user.getUser().getUserRoles()) {
roles[roles.length + 1] = role.getRole();
}
claims.put("roles", roles);
claims.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME));
}
String token = Jwts.builder().setClaims(claims)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, SECRET.getBytes()).compact();
response.addHeader(HEADER_STRING, TOKEN_PREFIX + token);
}
}
JWTAuthorizationFilter.java
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
public class JWTAuthorizationFilter extends BasicAuthenticationFilter {
public JWTAuthorizationFilter(AuthenticationManager authenticationManager) {
super(authenticationManager);
}
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
String header = request.getHeader(HEADER_STRING);
if (header == null || !header.startsWith(TOKEN_PREFIX)) {
chain.doFilter(request, response);
return;
}
UsernamePasswordAuthenticationToken authentication = getToken(request);
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(request, response);
}
#SuppressWarnings("unchecked")
private UsernamePasswordAuthenticationToken getToken(HttpServletRequest request) {
String token = request.getHeader(HEADER_STRING);
System.out.println("-----------------------------------------------------");
System.out.println("Token: " + token);
System.out.println("-----------------------------------------------------");
if (token != null) {
Claims claims = Jwts.parser().setSigningKey(SECRET.getBytes())
.parseClaimsJws(token.replace(TOKEN_PREFIX, "")).getBody();
String user = claims.getSubject();
ArrayList<String> roles = (ArrayList<String>) claims.get("roles");
ArrayList<MyGrantedAuthority> rolesList = new ArrayList<>();
if (roles != null) {
for (String role : roles) {
rolesList.add(new MyGrantedAuthority(role));
}
}
if (user != null) {
return new UsernamePasswordAuthenticationToken(user, null, null);
}
return null;
}
return null;
}
}
SecurityConfig.java
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Qualifier("userDetailsService")
#Autowired
CustomUserDetailsService userDetailsService;
#Autowired
PasswordEncoder passwordEncoder;
#Autowired
AuthenticationManager authenticationManager;
#Autowired
JWTAuthenticationEntryPoint jwtAuthenticationEntryPoint;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
try {
auth.userDetailsService(this.userDetailsService).passwordEncoder(passwordEncoder);
} catch (Exception e) {
}
}
/*
* #Autowired public void configureGlobal(AuthenticationManagerBuilder auth)
* throws Exception {
* auth.inMemoryAuthentication().withUser("student").password("student").roles(
* "student").and().withUser("admin") .password("admin").roles("admin"); }
*/
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
// http.authorizeRequests().anyRequest().permitAll();
// http.authorizeRequests().antMatchers("/api/**").permitAll();
http.addFilter(new JWTAuthenticationFilter(authenticationManager));
http.addFilter(new JWTAuthorizationFilter(authenticationManager));
http.authorizeRequests().antMatchers("/api/student/**").hasAnyRole("STUDENT", "ADMIN");
http.authorizeRequests().antMatchers("/api/admin/**").hasRole("ADMIN");
http.authorizeRequests().antMatchers("/api/libararian/**").hasAnyRole("LIBRARIAN", "ADMIN");
http.authorizeRequests().antMatchers("/api/staff/**").hasAnyRole("STAFF", "ADMIN");
http.authorizeRequests().antMatchers("/api/teacher/**").hasAnyRole("TEACHER", "ADMIN");
http.authorizeRequests().antMatchers("/api/parent/**").hasAnyRole("PARENT", "ADMIN");
http.httpBasic().authenticationEntryPoint(jwtAuthenticationEntryPoint);
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// http.formLogin().and().logout().logoutSuccessUrl("/login?logout").permitAll();
}
}
MyGrantedAuthority.java
public class MyGrantedAuthority implements GrantedAuthority {
String authority;
MyGrantedAuthority(String authority) {
this.authority = authority;
}
#Override
public String getAuthority() {
// TODO Auto-generated method stub
return authority;
}
}
JWTAuthenticationEntryPoint.java
#Component
public class JWTAuthenticationEntryPoint implements AuthenticationEntryPoint {
#Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception)
throws IOException, ServletException {
response.setStatus(403);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
String message;
if (exception.getCause() != null) {
message = exception.getCause().getMessage();
} else {
message = exception.getMessage();
}
byte[] body = new ObjectMapper().writeValueAsBytes(Collections.singletonMap("error", message));
response.getOutputStream().write(body);
}
}
I got it.
I followed another tutorial which made my job easy.
Here is the complete rewrite working code
TokenProvider.java
package com.cloudsofts.cloudschool.security;
import static com.cloudsofts.cloudschool.security.SecurityConstants.EXPIRATION_TIME;
import static com.cloudsofts.cloudschool.security.SecurityConstants.SECRET;
import java.util.ArrayList;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import com.cloudsofts.cloudschool.people.users.pojos.CustomUserDetails;
import com.cloudsofts.cloudschool.people.users.pojos.Role;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
#Component
public class TokenProvider {
#Autowired
CustomUserDetailsService userService;
public String createToken(String username) {
CustomUserDetails user = (CustomUserDetails) userService.loadUserByUsername(username);
Claims claims = Jwts.claims().setSubject(username);
ArrayList<String> rolesList = new ArrayList<String>();
for (Role role : user.getUser().getUserRoles()) {
rolesList.add(role.getRole());
}
claims.put("roles", rolesList);
String token = Jwts.builder().setClaims(claims)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)).setIssuedAt(new Date())
.signWith(SignatureAlgorithm.HS512, SECRET).compact();
return token;
}
public Authentication getAuthentication(String token) {
String username = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody().getSubject();
UserDetails userDetails = this.userService.loadUserByUsername(username);
return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities());
}
}
JWTFilter.java
package com.cloudsofts.cloudschool.security;
import static com.cloudsofts.cloudschool.security.SecurityConstants.HEADER_STRING;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.GenericFilterBean;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.UnsupportedJwtException;
public class JWTFilter extends GenericFilterBean {
public final static String AUTHORIZATION_HEADER = "Authorization";
private final TokenProvider tokenProvider;
public JWTFilter(TokenProvider tokenProvider) {
this.tokenProvider = tokenProvider;
}
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
throws IOException, ServletException {
try {
HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
String jwt = resolveToken(httpRequest);
if (jwt != null) {
Authentication authentication = this.tokenProvider.getAuthentication(jwt);
if (authentication != null) {
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
chain.doFilter(servletRequest, servletResponse);
} catch (ExpiredJwtException | UnsupportedJwtException | MalformedJwtException | SignatureException
| UsernameNotFoundException e) {
// Application.logger.info("Security exception {}", e.getMessage());
((HttpServletResponse) servletResponse).setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
}
private String resolveToken(HttpServletRequest request) {
String bearerToken = request.getHeader(HEADER_STRING);
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7, bearerToken.length());
}
return null;
}
}
JWTConfigurer.java
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
public class JWTConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
private final TokenProvider tokenProvider;
public JWTConfigurer(TokenProvider tokenProvider) {
this.tokenProvider = tokenProvider;
}
#Override
public void configure(HttpSecurity http) throws Exception {
JWTFilter customFilter = new JWTFilter(tokenProvider);
http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
}
}
SecurityConfig.java
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.cloudsofts.cloudschool.people.users.pojos.User;
#RestController
public class LoginController {
private AuthenticationManager authenticationManager;
private TokenProvider tokenProvider;
private CustomUserDetailsService userService;
LoginController(AuthenticationManager auth, CustomUserDetailsService service, TokenProvider tokenProvider) {
this.authenticationManager = auth;
this.userService = service;
this.tokenProvider = tokenProvider;
}
#PostMapping("/login")
public String getToken(#RequestBody User user, HttpServletResponse response) {
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(user.getUsername(),
user.getPassword());
authenticationManager.authenticate(authToken);
return tokenProvider.createToken(user.getUsername());
}
}
LoginController.java
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.cloudsofts.cloudschool.people.users.pojos.User;
#RestController
public class LoginController {
private AuthenticationManager authenticationManager;
private TokenProvider tokenProvider;
private CustomUserDetailsService userService;
LoginController(AuthenticationManager auth, CustomUserDetailsService service, TokenProvider tokenProvider) {
this.authenticationManager = auth;
this.userService = service;
this.tokenProvider = tokenProvider;
}
#PostMapping("/login")
public String getToken(#RequestBody User user, HttpServletResponse response) {
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(user.getUsername(),
user.getPassword());
authenticationManager.authenticate(authToken);
return tokenProvider.createToken(user.getUsername());
}
}
Link to the Github project that helped me.
I am also using jwt authentication on my project and I could see that you are missing an entry point which should be used on the project. I will tell you how I implemented it and see if it can help you =).
You need to implement an authenticationEntryPoint in order to tell the code how the authentication will be done. It can be added after the filters, on the http.authorizerequest, with the command:
.authenticationEntryPoint(jwtAuthEndPoint);
where jwtAuthEndPoint is the following component:
#Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
#Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
AuthenticationException e) throws IOException, ServletException {
httpServletResponse.setStatus(SC_FORBIDDEN);
httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
String message;
if (e.getCause() != null) {
message = e.getCause().getMessage();
} else {
message = e.getMessage();
}
byte[] body = new ObjectMapper().writeValueAsBytes(Collections.singletonMap("error", message));
httpServletResponse.getOutputStream().write(body);
}
}
I would also suggest you to take a look on this tutorial, which helped me A LOT in this case: https://sdqali.in/blog/2016/07/07/jwt-authentication-with-spring-web---part-4/
Related
I want to check response body, read the response then perform some other operation manipulate the body and then return the response.
How exactly can i log the response in logger?
If i want to manipulate the content of response how can i do that?
Custom Filter.java
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
#Component
#Order(1)
#WebFilter(urlPatterns = {"/*"}, description = "My delay filter ")
public class CustomFilter implements Filter{
private static final Logger logger = Logger.getLogger(CustomFilter.class);
#Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
try {
if (httpRequest.getRequestURL().toString().contains("download")) {
logger.debug(httpResponse); //want to log response body
}
} catch (Exception e) {
logger.error("Exception in CustomFilter.doFilter(): ", e);
}
chain.doFilter(request, response);
}
#Override
public void destroy() {
// TODO Auto-generated method stub
}
}
package com.biclinical.rmm.controller;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;
import org.springframework.web.util.WebUtils;
import com.biclinical.rmm.utility.ServiceUtils;
#Component
#Order(1)
#WebFilter(urlPatterns = { "/*" })
public class DownloadFileFilter implements Filter {
private static final Logger logger = Logger.getLogger(DownloadFileFilter.class);
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest requestToCache = new ContentCachingRequestWrapper((HttpServletRequest) request);
HttpServletResponse responseToCache = new ContentCachingResponseWrapper((HttpServletResponse) response);
try {
if (requestToCache.getRequestURL().toString().contains("/download")) {
chain.doFilter(request, responseToCache);
getResponseData(responseToCache);
} else {
chain.doFilter(request, response);
}
} catch (Exception e) {
logger.error("Exception in CustomFilter.doFilter(): ", e);
}
}
private static void getResponseData(HttpServletResponse response) throws Exception {
ContentCachingResponseWrapper wrapper = WebUtils.getNativeResponse(response,
ContentCachingResponseWrapper.class);
if (wrapper != null) {
byte[] buf = wrapper.getContentAsByteArray();
if (buf.length > 0) {
String payload = new String(buf, 0, buf.length, wrapper.getCharacterEncoding());
logger.debug("Response Richa :" + payload);
wrapper.copyBodyToResponse();
}
}
}
#Override
public void destroy() {
}
}
Whenever I am calling the API with endPoint /user/block using retrofit, The retrofit calling the API with root Url of the BASE_URL instead of full BASE_URL.
Like if my BASE_URL is.
BASE_URL = "http://111.111.111.11/SocialApi/public/";
Then the API call should be go on BASE_URL+endPoint, But the Api call is going on root of base Url,
http://111.111.111.11/user/block
So getting 404 Not Found response.
What actually I am doing wrong here?
My singleton class, ApiClient.java.
package com.socialcodia.famblah.api;
import android.util.Log;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.socialcodia.famblah.SocialCodia;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class ApiClient {
private static final String BASE_URL = "http://111.111.111.11/SocialApiFriendsSystemVideoThumb/public/";
public static final String HEADER_CACHE_CONTROL = "Cache-Control";
public static final String HEADER_PRAGMA = "Pragma";
private static final String TAG = "ServiceGenerator";
private static ApiClient mInstance;
private Retrofit retrofit;
public static final long CACHE_SIZE = 5 * 1024 * 1024;
private ApiClient()
{
Gson gson = new GsonBuilder()
.setLenient()
.create();
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient())
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
}
private static OkHttpClient okHttpClient(){
return new OkHttpClient.Builder()
.cache(cache())
.addInterceptor(httpLoggingInterceptor())
.addNetworkInterceptor(networkInterceptor())
.addInterceptor(offlineInterceptor())
.build();
}
private static Cache cache()
{
return new Cache(new File(SocialCodia.getInstance().getCacheDir(),"socialcodia"),CACHE_SIZE);
}
private static HttpLoggingInterceptor httpLoggingInterceptor()
{
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
#Override
public void log(String message) {
Log.d("mufazmi",message);
}
});
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
return httpLoggingInterceptor;
}
private static Interceptor networkInterceptor()
{
return new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Response response =chain.proceed(chain.request());
CacheControl cacheControl = new CacheControl.Builder()
.maxAge(20, TimeUnit.SECONDS)
.build();
return response.newBuilder()
.removeHeader(HEADER_PRAGMA)
.removeHeader(HEADER_CACHE_CONTROL)
.header(HEADER_CACHE_CONTROL,cacheControl.toString())
.build();
}
};
}
public static Interceptor offlineInterceptor()
{
return new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (!SocialCodia.isNetworkOk())
{
CacheControl cacheControl = new CacheControl.Builder()
.maxStale(7,TimeUnit.DAYS)
.build();
request = request.newBuilder()
.removeHeader(HEADER_PRAGMA)
.removeHeader(HEADER_CACHE_CONTROL)
.cacheControl(cacheControl)
.build();
}
return chain.proceed(request);
}
};
}
public static synchronized ApiClient getInstance()
{
if (mInstance == null)
{
mInstance = new ApiClient();
}
return mInstance;
}
public Api getApi()
{
return retrofit.create(Api.class);
}
}
My API interface.
package com.socialcodia.famblah.api;
import com.socialcodia.famblah.pojo.ResponseDefault;
import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.Header;
import retrofit2.http.POST;
import static com.socialcodia.famblah.storage.Constants.USER_TOKEN;
import static com.socialcodia.famblah.storage.Constants.USER_ID;
public interface Api
{
#FormUrlEncoded
#POST("/user/block")
Call<ResponseDefault> doBlock(
#Header(USER_TOKEN) String token,
#Field(USER_ID) int userId
);
#FormUrlEncoded
#POST("acceptFriendRequest")
Call<ResponseDefault> acceptFriendRequest(
#Header(USER_TOKEN) String token,
#Field(USER_ID) int userId
);
}
Method to call api from ProfileActivity
private void doBlock()
{
Call<ResponseDefault> call = ApiClient.getInstance().getApi().doBlock(token,hisUserId);
call.enqueue(new Callback<ResponseDefault>() {
#Override
public void onResponse(Call<ResponseDefault> call, Response<ResponseDefault> response) {
if (response.isSuccessful())
{
ResponseDefault responseDefault = response.body();
Toast.makeText(ProfileActivity.this, responseDefault.getMessage(), Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<ResponseDefault> call, Throwable t) {
Toast.makeText(ProfileActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
t.printStackTrace();
}
});
}
But when I am calling the acceptFriendRequest() method it's working. means it calling the API.
Method to accept friend request.
private void acceptFriendRequest()
{
if (Utils.isNetworkAvailable(getApplicationContext()))
{
btnAcceptFriendRequest.setEnabled(false);
Call<ResponseDefault> call = ApiClient.getInstance().getApi().acceptFriendRequest(token,hisUserId);
call.enqueue(new Callback<ResponseDefault>() {
#Override
public void onResponse(Call<ResponseDefault> call, Response<ResponseDefault> response) {
if (response.isSuccessful())
{
ResponseDefault responseDefault = response.body();
if (!responseDefault.getError())
{
btnAcceptFriendRequest.setEnabled(true);
btnRejectFriendRequest.setVisibility(View.GONE);
btnAcceptFriendRequest.setVisibility(View.GONE);
btnUnFriend.setVisibility(View.VISIBLE);
}
else
{
btnAcceptFriendRequest.setEnabled(true);
Toast.makeText(ProfileActivity.this, responseDefault.getMessage(), Toast.LENGTH_SHORT).show();
}
}
else
{
btnAcceptFriendRequest.setEnabled(true);
Toast.makeText(ProfileActivity.this, R.string.SNR, Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<ResponseDefault> call, Throwable t) {
btnAcceptFriendRequest.setEnabled(true);
t.printStackTrace();
}
});
}
}
I have solve this by removing the slash from endPoint /user/block
#FormUrlEncoded
#POST("user/block")
Call<ResponseDefault> doBlock(
#Header(USER_TOKEN) String token,
#Field(USER_ID) int userId
);
I have a problem getting my JWT Token verified, despite it giving me the correct payload.
Excuse me if I'm a little insecure in this part of the code, since this was handed out by our teacher via a template, but we are unable to reach him.
We had to make some changes to the code itself, since it had the username put into the token and we want the email put in.
We are using something called UserPrincipal, what I can understand, its used to determine access rights to a file or object and originally we used roles to determine what users had access to which endpoints. This is not the case in this project, since its a short demo based on other features.
How does our user principal class look like?
package rest;
import entity.User;
import java.security.Principal;
public class UserPrincipal implements Principal {
private String name;
private String email;
public UserPrincipal(User user) {
this.email = user.getEmail();
}
public UserPrincipal(String email) {
super();
this.email = email;
}
#Override
public String getName() {
return email;
}
}
See, here the user principal used to also get a list of roles and instead of a email, it got a username.
Where do we use this user principal? Well, we use it when we generate our token. This is also here we have our endpoint, yes it should be moved to our interface class.
package rest;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.JWSSigner;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
import entity.User;
import facade.UserFacade;
import exceptions.AuthenticationException;
import exceptions.GenericExceptionMapper;
import utils.PuSelector;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
#Path("login")
public class LoginEndpoint {
private static final int TOKEN_EXPIRE_TIME = 1000 * 60 * 30; // ms * sec * min = 30 min
private static final UserFacade USER_FACADE = UserFacade.getInstance(PuSelector.getEntityManagerFactory("pu"));
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response login(String jsonString) throws AuthenticationException {
JsonObject json = new JsonParser().parse(jsonString).getAsJsonObject();
String email = json.get("email").getAsString();
String password = json.get("password").getAsString();
String ip = json.get("ip").getAsString();
try {
User user = USER_FACADE.getVeryfiedUser(email, password, ip);
String code = USER_FACADE.sendCode(email);
String token = createToken(email);
JsonObject responseJson = new JsonObject();
responseJson.addProperty("code", code);
responseJson.addProperty("email", email);
responseJson.addProperty("token", token);
return Response.ok(new Gson().toJson(responseJson)).build();
} catch (JOSEException | AuthenticationException ex) {
if (ex instanceof AuthenticationException) {
throw (AuthenticationException) ex;
}
Logger.getLogger(GenericExceptionMapper.class.getName()).log(Level.SEVERE, null, ex);
}
throw new AuthenticationException("Somthing went wrong! Please try again");
}
private String createToken(String email) throws JOSEException {
//String firstNameLetter = user.getFirstName().substring(0, 1);
//String lastNameLetter = user.getLastName().substring(0, 1);
//int ageTimesID = user.getAge() * user.getId();
//String name = firstNameLetter + lastNameLetter + ageTimesID;
String issuer = "the_turtle_troopers";
JWSSigner signer = new MACSigner(SharedSecret.getSharedKey());
Date date = new Date();
JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
.subject(email)
.claim("email", email)
.claim("allowed", true)
.claim("issuer", issuer)
.issueTime(date)
.expirationTime(new Date(date.getTime() + TOKEN_EXPIRE_TIME))
.build();
SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.HS256), claimsSet);
signedJWT.sign(signer);
return signedJWT.serialize();
}
}
We have a security context class.. Not quite sure if this has any impact on my problem, but regardless:
package rest;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.core.SecurityContext;
import java.security.Principal;
public class JWTSecurityContext implements SecurityContext {
UserPrincipal user;
ContainerRequestContext request;
public JWTSecurityContext(UserPrincipal user, ContainerRequestContext request) {
this.user = user;
this.request = request;
}
#Override
public boolean isUserInRole(String role) {
return true;
}
#Override
public boolean isSecure() {
return request.getUriInfo().getBaseUri().getScheme().equals("https");
}
#Override
public Principal getUserPrincipal() {
return user;
}
#Override
public String getAuthenticationScheme() {
return "JWT"; //Only for INFO
}
}
And finally we have our JWTAuthenticationFilter:
package rest;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.crypto.MACVerifier;
import com.nimbusds.jwt.SignedJWT;
import exceptions.AuthenticationException;
import javax.annotation.Priority;
import javax.annotation.security.DenyAll;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.Context;
import javax.ws.rs.ext.Provider;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.text.ParseException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
#Provider
#Priority(Priorities.AUTHENTICATION)
public class JWTAuthenticationFilter implements ContainerRequestFilter {
private static final List<Class<? extends Annotation>> securityAnnotations
= Arrays.asList(DenyAll.class, PermitAll.class, RolesAllowed.class);
#Context
private ResourceInfo resourceInfo;
#Override
public void filter(ContainerRequestContext request) throws IOException {
if (isSecuredResource()) {
String token = request.getHeaderString("x-access-token");//
if (token == null) {
request.abortWith(exceptions.GenericExceptionMapper.makeErrRes(token, 403));
return;
}
try {
UserPrincipal user = getUserPrincipalFromTokenIfValid(token);
//What if the client had logged out????
request.setSecurityContext(new JWTSecurityContext(user, request));
} catch (AuthenticationException | ParseException | JOSEException ex) {
Logger.getLogger(JWTAuthenticationFilter.class.getName()).log(Level.SEVERE, null, ex);
request.abortWith(exceptions.GenericExceptionMapper.makeErrRes("Token not valid (timed out?)", 403));
}
}
}
private boolean isSecuredResource() {
for (Class<? extends Annotation> securityClass : securityAnnotations) {
if (resourceInfo.getResourceMethod().isAnnotationPresent(securityClass)) {
return true;
}
}
for (Class<? extends Annotation> securityClass : securityAnnotations) {
if (resourceInfo.getResourceClass().isAnnotationPresent(securityClass)) {
return true;
}
}
return false;
}
private UserPrincipal getUserPrincipalFromTokenIfValid(String token) throws ParseException, JOSEException, AuthenticationException {
SignedJWT signedJWT = SignedJWT.parse(token);
//Is it a valid token (generated with our shared key)
JWSVerifier verifier = new MACVerifier(SharedSecret.getSharedKey());
if (signedJWT.verify(verifier)) {
if (new Date().getTime() > signedJWT.getJWTClaimsSet().getExpirationTime().getTime()) {
throw new AuthenticationException("Your Token is no longer valid");
}
String email = signedJWT.getJWTClaimsSet().getClaim("email").toString();
return new UserPrincipal(email);
} else {
throw new JOSEException("User could not be extracted from token");
}
}
}
Hope someone will be able to tell me why it is my token isn't getting validated on jwt.io
I'm trying to migrate from Spring XML based configuration to Pure Java Configuration, I have configured all the configuration files, but when I try to enter the username and password in login page, it redirects me back to the login page again. I believe the userServiceImpl method is not being invoked because the control is not going there.
Here, I have autowired userServiceImpl method which is implementing UserDetailsService of spring security core credentials.
package com.lw.sms.config;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.orm.hibernate4.LocalSessionFactoryBuilder;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import com.lw.sms.CustomAuthenticationSuccessHandler;
import com.lw.sms.UserServiceImpl;
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
#EnableTransactionManagement
#Order(1000)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);
#Value("${jdbc.dialect}")
String jdbcDialect;
#Value("${jdbc.driverClassName}")
String jdbcDriverClassName;
#Value("${jdbc.databaseurl}")
String jdbcDatabaseurl;
#Value("${jdbc.username}")
String jdbcusername;
#Value("${jdbc.password}")
String jdbcPassword;
#Autowired
private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;
#Autowired
private UserServiceImpl userServiceImpl;
#Override
public void configure(final AuthenticationManagerBuilder auth) throws Exception {
logger.info("configure auth");
auth.userDetailsService(userServiceImpl);
}
#Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
#Override
public void configure(HttpSecurity http) throws Exception {
logger.info("configure http");
http.httpBasic().disable();
http.authorizeRequests().and().formLogin().loginPage("/login").usernameParameter("employeeId")
.passwordParameter("password").successHandler(customAuthenticationSuccessHandler)
.failureUrl("/login?error").defaultSuccessUrl("/dashboard", true)
.loginProcessingUrl("j_spring_security_check")
.and().logout().logoutUrl("/j_spring_security_logout").logoutSuccessUrl("/logout")
.invalidateHttpSession(true).deleteCookies("JSESSIONID")
.and().sessionManagement().invalidSessionUrl("/logout").maximumSessions(1)
.maxSessionsPreventsLogin(true).expiredUrl("/logout");
http.csrf().disable();
http.authorizeRequests().anyRequest().authenticated();
}
#Bean
public SessionRegistry sessionRegistry() {
logger.info("sessionRegistry");
return new SessionRegistryImpl();
}
#Bean
public SessionFactory sessionFactory() {
LocalSessionFactoryBuilder builder = new LocalSessionFactoryBuilder(dataSource());
builder.scanPackages("com.lw.sms").addProperties(hibernateProperties());
return builder.buildSessionFactory();
}
#Bean
public LocalSessionFactoryBean hibernateSessionFactory() {
logger.info("sessionFactory");
org.hibernate.cfg.Configuration configuration = new org.hibernate.cfg.Configuration();
configuration.configure("hibernate.cfg.xml");
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan("com.lw.sms");
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public DataSource dataSource() {
logger.info("dataSource");
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(jdbcDriverClassName);
dataSource.setUrl(jdbcDatabaseurl);
dataSource.setUsername(jdbcusername);
dataSource.setPassword(jdbcPassword);
return dataSource;
}
#Bean
#Autowired
public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
logger.info("transactionManager");
HibernateTransactionManager htm = new HibernateTransactionManager();
htm.setSessionFactory(sessionFactory);
return htm;
}
#Bean
public Properties hibernateProperties() {
logger.info("hibernateProperties");
Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.show_sql", "true");
hibernateProperties.setProperty("hibernate.dialect", jdbcDialect);
hibernateProperties.setProperty("hibernate.default_schema", "sms");
return hibernateProperties;
}
}
CustomAuthenticationSuccessHandler Code is attached below
package com.lw.sms;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.WebAttributes;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.stereotype.Component;
import com.lw.sms.constants.Constants;
import com.lw.sms.user.entities.EmployeeEntity;
import com.lw.sms.user.entities.EmployeePermissionsEntity;
import com.lw.sms.user.service.UserManagementService;
import com.lw.sms.util.QueryBuilder;
#Component("customAuthenticationSuccessHandler")
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
private static final Logger logger = LoggerFactory.getLogger(CustomAuthenticationSuccessHandler.class);
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
#Autowired
#Qualifier("sessionInfo")
private SessionInfo sessionInfo;
#Autowired
#Qualifier("userManagementServiceImpl")
private UserManagementService userManagementService;
#Autowired
private HttpServletRequest httpServletRequest;
#Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException {
response.setStatus(HttpServletResponse.SC_OK);
clearAuthenticationAttributes(request);
handle(request, response);
}
protected void handle(HttpServletRequest request, HttpServletResponse response)
throws IOException {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof UserDetails) {
EmployeeEntity employeeEntity = (EmployeeEntity) principal;
setSessionInformationForEmployee(employeeEntity);
}
if (response.isCommitted()) {
return;
}
startServices();
redirectStrategy.sendRedirect(request, response, "/dashboard");
}
/**
* #param employeeEntity
*
*/
private void setSessionInformationForEmployee(EmployeeEntity employeeEntity) {
try {
WebAuthenticationDetails details = (WebAuthenticationDetails) SecurityContextHolder.getContext()
.getAuthentication().getDetails();
userManagementService.updateLoginInfo(employeeEntity.getUsername(), details.getRemoteAddress());
// setting session information
} catch (Exception e) {
logger.info("Exception while set Session Information For Employee :" + ExceptionUtils.getFullStackTrace(e));
}
}
private void startServices() {
logger.info("Starting Services..");
try {
String domainName = httpServletRequest.getScheme() + "://" + httpServletRequest.getServerName();
if (httpServletRequest.getServerPort() != 0) {
domainName += ":" + httpServletRequest.getServerPort();
}
domainName += httpServletRequest.getContextPath();
Constants.domainName = domainName + "/resources";
} catch (Exception e) {
logger.error("Error in start services :"+ ExceptionUtils.getFullStackTrace(e));
}
}
protected void clearAuthenticationAttributes(HttpServletRequest request) {
HttpSession session = request.getSession(false);
if (session == null) {
return;
}
session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
}
public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
this.redirectStrategy = redirectStrategy;
}
protected RedirectStrategy getRedirectStrategy() {
return redirectStrategy;
}
}
UserServiceImpl Code is attached below
package com.lw.sms;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.lw.sms.user.dao.UserManagementDAO;
import com.lw.sms.user.entities.EmployeeEntity;
#Service("userServiceImpl")
public class UserServiceImpl implements UserDetailsService {
#Autowired
#Qualifier("userManagementDAOImpl")
private UserManagementDAO userManagementDAO;
#Override
#Transactional
public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException {
EmployeeEntity employeeEntity = userManagementDAO.loadUserByUsername(username);
if (employeeEntity == null) {
ContractorEntity contractorEntity = userManagementDAO.loadUserByUsernameContractor(username);
if(contractorEntity == null)
throw new AuthenticationCredentialsNotFoundException("Invalid Username or Password");
}
if(!employeeEntity.isEnabled())
throw new AuthenticationCredentialsNotFoundException("Employee Disabled");
return employeeEntity;
}
}
Global Exception Handler Code:
package com.lw.sms;
import java.io.IOException;
import java.nio.charset.Charset;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.json.simple.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.stereotype.Controller;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.HttpSessionRequiredException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException;
#SuppressWarnings("deprecation")
#Controller
#ControllerAdvice
public class CustomExceptionHandler extends RuntimeException {
/**
*
*/
private static final long serialVersionUID = 3699167829164697594L;
private static final Logger logger = LoggerFactory
.getLogger(CustomExceptionHandler.class);
#ExceptionHandler(AuthenticationCredentialsNotFoundException.class)
#ResponseStatus(HttpStatus.UNAUTHORIZED)
public ModelAndView handleLoginExceptions(HttpServletRequest request,
HttpServletResponse response,Exception exception) {
logger.info("Handling exception time error"+ exception.getMessage());
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("login");
return modelAndView;
}
#ExceptionHandler(HttpSessionRequiredException.class)
public String handleSessionExpired() {
logger.info("session-expired");
return "logout";
}
#SuppressWarnings("unchecked")
#ExceptionHandler(value = { MissingServletRequestParameterException.class,
ServletRequestBindingException.class, TypeMismatchException.class,
HttpMessageNotReadableException.class,
MethodArgumentNotValidException.class,
MissingServletRequestPartException.class })
#ResponseStatus(value = HttpStatus.BAD_REQUEST, reason = "Bad Request")
#ResponseBody
public JSONObject handle400Exception(Exception ex,HttpServletResponse response) {
logger.error("400 Exception" + ex.getMessage());
JSONObject jsonObject=new JSONObject();
jsonObject.put("status", HttpStatus.BAD_REQUEST);
jsonObject.put("success", false);
jsonObject.put("message", ex.getMessage());
try {
response.getOutputStream().write(jsonObject.toString().getBytes(Charset.defaultCharset()));
} catch (IOException e) {
logger.error(ExceptionUtils.getFullStackTrace(e));
}
response.setContentType("application/json; charset=UTF-8");
return jsonObject;
}
#ExceptionHandler(value = { NoSuchRequestHandlingMethodException.class, })
#ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "Not Found")
#ResponseBody
public Boolean handle404Exception(Exception ex) {
logger.error("404 Exception" + ExceptionUtils.getFullStackTrace(ex));
return false;
}
#ExceptionHandler(value = { HttpRequestMethodNotSupportedException.class,
HttpMediaTypeNotSupportedException.class })
#ResponseStatus(value = HttpStatus.NOT_ACCEPTABLE, reason = "Not Supported")
#ResponseBody
public Boolean handle405Exception(Exception ex) {
logger.error("405 Exception" + ExceptionUtils.getFullStackTrace(ex));
return false;
}
#ExceptionHandler(value = { HttpMessageNotWritableException.class,
ConversionNotSupportedException.class })
#ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR, reason = "Internal Server Error")
#ResponseBody
public Boolean handle500Exception(Exception ex) {
logger.error("500 Exception" + ExceptionUtils.getFullStackTrace(ex));
return false;
}
#ExceptionHandler({ Exception.class })
public ModelAndView handleException(Exception ex, HttpServletRequest request,
HttpServletResponse response) {
logger.info("*****************************************************");
logger.error("Exception: " + ExceptionUtils.getFullStackTrace(ex));
ex.printStackTrace();
logger.info("*****************************************************");
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("logout");
return modelAndView;
}
}
This is my HomeController.
package com.lw.sms;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.ModelAndView;
import com.lw.sms.master.service.MasterDataService;
import com.lw.sms.user.entities.EmployeeEntity;
/**
* Handles requests for the application home page.
*/
#Controller("homeController")
public class HomeController {
#Autowired
#Qualifier("masterDataServiceImpl")
private MasterDataService masterDataService;
#Autowired
#Qualifier("sessionInfo")
private SessionInfo sessionInfo;
#GetMapping(value = { "/home", "/", "login" })
public ModelAndView home() {
return new ModelAndView("login");
}
#GetMapping(value = "dashboard")
public ModelAndView dashboard() {
EmployeeEntity user = sessionInfo.getEmployeeEntity();
return new ModelAndView("dashboard", "userDetails", user);
}
// Logout page
#ResponseStatus(code = HttpStatus.UNAUTHORIZED)
#GetMapping(value = "logout")
public String logout() {
return "logout";
}
}
Could you please try adding the successForwardUrl also as below.
http.authorizeRequests().antMatchers("/login").permitAll()
.antMatchers("/dashboard").access("IS_AUTHENTICATED_FULLY")
.antMatchers("/j_spring_security_check").access("IS_AUTHENTICATED_ANONYMOUSLY")
.and().formLogin().loginPage("/login").usernameParameter("employeeId").passwordParameter("password")
.successForwardUrl("/dashboard").defaultSuccessUrl("/dashboard", true).failureForwardUrl("/loginfailed")
.loginProcessingUrl("/j_spring_security_check")
.and().logout().logoutSuccessUrl("/logout").invalidateHttpSession(true)
.and().sessionManagement().sessionFixation().none()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.invalidSessionUrl("/login")
.and().exceptionHandling().accessDeniedPage("/Access_Denied").and().csrf().disable();
I was able to replicate the error.
I had to configure a new bean in SecurityConfig file.
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userServiceImpl);
authenticationProvider.setPasswordEncoder(passwordEncoder());
return authenticationProvider;
}
I'm developing an Apache Sling WCMS application. I need to filter all requests sent to the server and set some headers in response object. I implemented filter and bundle activator class according to Felix Http Filter Sample and installed as bundle to sling.
Fileter class:
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class HeaderFilter implements Filter {
private final String name;
public HeaderFilter(String name) {
this.name = name;
}
public void init(FilterConfig config) throws ServletException {
doLog("Init with config [" + config + "]");
}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
try {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
doLog("Filter request [" + request + "]");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Expires", "-1");
chain.doFilter(req, response);
} catch (Exception e) {
e.printStackTrace();
}
}
public void destroy() {
doLog("Destroyed filter");
}
private void doLog(String message) {
System.out.println("## [" + this.name + "] " + message);
}
}
Bundle Activator class:
import org.apache.felix.http.api.ExtHttpService;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;
import java.util.Dictionary;
import java.util.Hashtable;
public class Activator implements BundleActivator {
private ServiceTracker tracker;
private HeaderFilter filter1 = new HeaderFilter("filter1");
Dictionary hashTable = new Hashtable<Object, Object>();
public void start(BundleContext context) throws Exception {
try {
this.tracker = new ServiceTracker(context, ExtHttpService.class.getName(), null) {
#Override
public Object addingService(ServiceReference ref) {
Object service = super.addingService(ref);
serviceAdded((ExtHttpService) service);
return service;
}
#Override
public void removedService(ServiceReference ref, Object service) {
serviceRemoved((ExtHttpService) service);
super.removedService(ref, service);
}
};
this.tracker.open();
} catch (Exception e) {
e.printStackTrace();
}
}
public void stop(BundleContext context)
throws Exception {
this.tracker.close();
}
private void serviceAdded(ExtHttpService service) {
try {
hashTable.put("filter.scope", new String[]{"request", "forward", "include"});
service.registerFilter(this.filter1, ".*", hashTable, 0, null);
} catch (Exception e) {
e.printStackTrace();
}
}
private void serviceRemoved(ExtHttpService service) {
service.unregisterFilter(this.filter1);
}
}
The is a problem with the code above. It's not working and no request will be filtered.
Any help is appreciated in advance.
Note that you can implement this in a much simpler way using Sling Filters implemented as OSGi Declarative Services (DS).
You'll then just need a few annotations in your Filter, no Activator and the correct pom.xml setup for the Maven plugins that handle the DS annotations.
The documentation is at https://sling.apache.org/documentation/the-sling-engine/filters.html and it points to the NoPropertyFilter example from the Sling integration tests.
I found that my filter is not tracked by the service tracker, so by passing parameter 'true' to tracker.open() the filter was tracked:
this.tracker.open(true);