Guest User

Untitled

a guest
Dec 16th, 2017
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.73 KB | None | 0 0
  1. @Configuration
  2. @EnableWebSecurity
  3. public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  4. public static final String JWT_TOKEN_HEADER_PARAM = "X-Authorization";
  5. public static final String FORM_BASED_LOGIN_ENTRY_POINT = "/api/auth/login";
  6. public static final String TOKEN_BASED_AUTH_ENTRY_POINT = "/api/**";
  7. public static final String TOKEN_REFRESH_ENTRY_POINT = "/api/auth/token";
  8.  
  9. @Autowired private RestAuthenticationEntryPoint authenticationEntryPoint;
  10. @Autowired private AuthenticationSuccessHandler successHandler;
  11. @Autowired private AuthenticationFailureHandler failureHandler;
  12. @Autowired private AjaxAuthenticationProvider ajaxAuthenticationProvider;
  13. @Autowired private JwtAuthenticationProvider jwtAuthenticationProvider;
  14.  
  15. @Autowired private TokenExtractor tokenExtractor;
  16.  
  17. @Autowired private AuthenticationManager authenticationManager;
  18.  
  19. @Autowired private ObjectMapper objectMapper;
  20.  
  21. protected AjaxLoginProcessingFilter buildAjaxLoginProcessingFilter() throws Exception {
  22. AjaxLoginProcessingFilter filter = new AjaxLoginProcessingFilter(FORM_BASED_LOGIN_ENTRY_POINT, successHandler, failureHandler, objectMapper);
  23. filter.setAuthenticationManager(this.authenticationManager);
  24. return filter;
  25. }
  26.  
  27. protected JwtTokenAuthenticationProcessingFilter buildJwtTokenAuthenticationProcessingFilter() throws Exception {
  28. List<String> pathsToSkip = Arrays.asList(TOKEN_REFRESH_ENTRY_POINT, FORM_BASED_LOGIN_ENTRY_POINT);
  29. SkipPathRequestMatcher matcher = new SkipPathRequestMatcher(pathsToSkip, TOKEN_BASED_AUTH_ENTRY_POINT);
  30. JwtTokenAuthenticationProcessingFilter filter
  31. = new JwtTokenAuthenticationProcessingFilter(failureHandler, tokenExtractor, matcher);
  32. filter.setAuthenticationManager(this.authenticationManager);
  33. return filter;
  34. }
  35.  
  36. @Bean
  37. @Override
  38. public AuthenticationManager authenticationManagerBean() throws Exception {
  39. return super.authenticationManagerBean();
  40. }
  41.  
  42. @Override
  43. protected void configure(AuthenticationManagerBuilder auth) {
  44. auth.authenticationProvider(ajaxAuthenticationProvider);
  45. auth.authenticationProvider(jwtAuthenticationProvider);
  46. }
  47.  
  48. @Bean
  49. protected BCryptPasswordEncoder passwordEncoder() {
  50. return new BCryptPasswordEncoder();
  51. }
  52.  
  53. @Override
  54. protected void configure(HttpSecurity http) throws Exception {
  55. http
  56. .csrf().disable() // We don't need CSRF for JWT based authentication
  57. .exceptionHandling()
  58. .authenticationEntryPoint(this.authenticationEntryPoint)
  59.  
  60. .and()
  61. .sessionManagement()
  62. .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
  63.  
  64. .and()
  65. .authorizeRequests()
  66. .antMatchers(FORM_BASED_LOGIN_ENTRY_POINT).permitAll() // Login end-point
  67. .antMatchers(TOKEN_REFRESH_ENTRY_POINT).permitAll() // Token refresh end-point
  68. .antMatchers("/console").permitAll() // H2 Console Dash-board - only for testing
  69. .and()
  70. .authorizeRequests()
  71. .antMatchers(TOKEN_BASED_AUTH_ENTRY_POINT).authenticated() // Protected API End-points
  72. .and()
  73. .addFilterBefore(buildAjaxLoginProcessingFilter(), UsernamePasswordAuthenticationFilter.class)
  74. .addFilterBefore(buildJwtTokenAuthenticationProcessingFilter(), UsernamePasswordAuthenticationFilter.class);
  75. }
  76. }
  77.  
  78. public class SkipPathRequestMatcher implements RequestMatcher {
  79. private OrRequestMatcher matchers;
  80. private RequestMatcher processingMatcher;
  81.  
  82. public SkipPathRequestMatcher(List<String> pathsToSkip, String processingPath) {
  83. Assert.notNull(pathsToSkip);
  84. List<RequestMatcher> m = pathsToSkip.stream().map(path -> new AntPathRequestMatcher(path)).collect(Collectors.toList());
  85. matchers = new OrRequestMatcher(m);
  86. processingMatcher = new AntPathRequestMatcher(processingPath);
  87. }
  88.  
  89. @Override
  90. public boolean matches(HttpServletRequest request) {
  91. if (matchers.matches(request)) {
  92. return false;
  93. }
  94. return processingMatcher.matches(request) ? true : false;
  95. }
  96. }
  97.  
  98. @Component
  99. public class JwtAuthenticationProvider implements AuthenticationProvider {
  100. private final JwtSettings jwtSettings;
  101.  
  102. @Autowired
  103. public JwtAuthenticationProvider(JwtSettings jwtSettings) {
  104. this.jwtSettings = jwtSettings;
  105. }
  106.  
  107. @Override
  108. public Authentication authenticate(Authentication authentication) throws AuthenticationException {
  109. RawAccessJwtToken rawAccessToken = (RawAccessJwtToken) authentication.getCredentials();
  110.  
  111. Jws<Claims> jwsClaims = rawAccessToken.parseClaims(jwtSettings.getTokenSigningKey());
  112. String subject = jwsClaims.getBody().getSubject();
  113. List<String> scopes = jwsClaims.getBody().get("scopes", List.class);
  114. List<GrantedAuthority> authorities = scopes.stream()
  115. .map(authority -> new SimpleGrantedAuthority(authority))
  116. .collect(Collectors.toList());
  117.  
  118. UserContext context = UserContext.create(subject, authorities);
  119.  
  120. return new JwtAuthenticationToken(context, context.getAuthorities());
  121. }
  122.  
  123. @Override
  124. public boolean supports(Class<?> authentication) {
  125. return (JwtAuthenticationToken.class.isAssignableFrom(authentication));
  126. }
  127. }
  128.  
  129. @Component
  130. public class JwtHeaderTokenExtractor implements TokenExtractor {
  131. public static String HEADER_PREFIX = "Bearer ";
  132.  
  133. @Override
  134. public String extract(String header) {
  135. if (StringUtils.isBlank(header)) {
  136. throw new AuthenticationServiceException("Authorization header cannot be blank!");
  137. }
  138.  
  139. if (header.length() < HEADER_PREFIX.length()) {
  140. throw new AuthenticationServiceException("Invalid authorization header size.");
  141. }
  142.  
  143. return header.substring(HEADER_PREFIX.length(), header.length());
  144. }
  145. }
  146.  
  147. public class JwtTokenAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter {
  148. private final AuthenticationFailureHandler failureHandler;
  149. private final TokenExtractor tokenExtractor;
  150.  
  151. @Autowired
  152. public JwtTokenAuthenticationProcessingFilter(AuthenticationFailureHandler failureHandler,
  153. TokenExtractor tokenExtractor, RequestMatcher matcher) {
  154. super(matcher);
  155. this.failureHandler = failureHandler;
  156. this.tokenExtractor = tokenExtractor;
  157. }
  158.  
  159. @Override
  160. public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
  161. throws AuthenticationException, IOException, ServletException {
  162. String tokenPayload = request.getHeader(WebSecurityConfig.JWT_TOKEN_HEADER_PARAM);
  163. RawAccessJwtToken token = new RawAccessJwtToken(tokenExtractor.extract(tokenPayload));
  164. return getAuthenticationManager().authenticate(new JwtAuthenticationToken(token));
  165. }
  166.  
  167. @Override
  168. protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
  169. Authentication authResult) throws IOException, ServletException {
  170. SecurityContext context = SecurityContextHolder.createEmptyContext();
  171. context.setAuthentication(authResult);
  172. SecurityContextHolder.setContext(context);
  173. chain.doFilter(request, response);
  174. }
  175.  
  176. @Override
  177. protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
  178. AuthenticationException failed) throws IOException, ServletException {
  179. SecurityContextHolder.clearContext();
  180. failureHandler.onAuthenticationFailure(request, response, failed);
  181. }
  182. }
  183.  
  184. public class AjaxLoginProcessingFilter extends AbstractAuthenticationProcessingFilter {
  185. private static Logger logger = LoggerFactory.getLogger(AjaxLoginProcessingFilter.class);
  186.  
  187. private final AuthenticationSuccessHandler successHandler;
  188. private final AuthenticationFailureHandler failureHandler;
  189.  
  190. private final ObjectMapper objectMapper;
  191.  
  192. public AjaxLoginProcessingFilter(String defaultProcessUrl, AuthenticationSuccessHandler successHandler,
  193. AuthenticationFailureHandler failureHandler, ObjectMapper mapper) {
  194. super(defaultProcessUrl);
  195. this.successHandler = successHandler;
  196. this.failureHandler = failureHandler;
  197. this.objectMapper = mapper;
  198. }
  199.  
  200. @Override
  201. public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
  202. throws AuthenticationException, IOException, ServletException {
  203. if (!HttpMethod.POST.name().equals(request.getMethod()) || !WebUtil.isAjax(request)) {
  204. if(logger.isDebugEnabled()) {
  205. logger.debug("Authentication method not supported. Request method: " + request.getMethod());
  206. }
  207. throw new AuthMethodNotSupportedException("Authentication method not supported");
  208. }
  209.  
  210. LoginRequest loginRequest = objectMapper.readValue(request.getReader(), LoginRequest.class);
  211.  
  212. if (StringUtils.isBlank(loginRequest.getUsername()) || StringUtils.isBlank(loginRequest.getPassword())) {
  213. throw new AuthenticationServiceException("Username or Password not provided");
  214. }
  215.  
  216. UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword());
  217.  
  218. return this.getAuthenticationManager().authenticate(token);
  219. }
  220.  
  221. @Override
  222. protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
  223. Authentication authResult) throws IOException, ServletException {
  224. successHandler.onAuthenticationSuccess(request, response, authResult);
  225. }
  226.  
  227. @Override
  228. protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
  229. AuthenticationException failed) throws IOException, ServletException {
  230. SecurityContextHolder.clearContext();
  231. failureHandler.onAuthenticationFailure(request, response, failed);
  232. }
  233. }
  234.  
  235. @Component
  236. public class AjaxAuthenticationProvider implements AuthenticationProvider {
  237. private final BCryptPasswordEncoder encoder;
  238. private final DatabaseUserService userService;
  239.  
  240. @Autowired
  241. public AjaxAuthenticationProvider(final DatabaseUserService userService, final BCryptPasswordEncoder encoder) {
  242. this.userService = userService;
  243. this.encoder = encoder;
  244. }
  245.  
  246. @Override
  247. public Authentication authenticate(Authentication authentication) throws AuthenticationException {
  248. Assert.notNull(authentication, "No authentication data provided");
  249.  
  250. String username = (String) authentication.getPrincipal();
  251. String password = (String) authentication.getCredentials();
  252.  
  253. User user = userService.getByUsername(username).orElseThrow(() -> new UsernameNotFoundException("User not found: " + username));
  254.  
  255. if (!encoder.matches(password, user.getPassword())) {
  256. throw new BadCredentialsException("Authentication Failed. Username or Password not valid.");
  257. }
  258.  
  259. if (user.getRoles() == null) throw new InsufficientAuthenticationException("User has no roles assigned");
  260.  
  261. List<GrantedAuthority> authorities = user.getRoles().stream()
  262. .map(authority -> new SimpleGrantedAuthority(authority.getRole().authority()))
  263. .collect(Collectors.toList());
  264.  
  265. UserContext userContext = UserContext.create(user.getUsername(), authorities);
  266.  
  267. return new UsernamePasswordAuthenticationToken(userContext, null, userContext.getAuthorities());
  268. }
  269.  
  270. @Override
  271. public boolean supports(Class<?> authentication) {
  272. return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
  273. }
  274. }
Add Comment
Please, Sign In to add comment