During my Spring Boot 1.3.1.RELEASE application startup I noticed a following line in the log:
Using default security password: d60d96ca-1285-41c9-aed7-d5688af74688
What does it mean and how to fix it ?
I suspect I have some issues in the my application config:
Application:
#SpringBootApplication
#EnableOAuth2Client
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
WebSecurityConfiguration:
#Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private OAuth2ClientContext oauth2ClientContext;
#Value("${ok.client.publicKey}")
private String okClientPublicKey;
#Override
public void configure(HttpSecurity http) throws Exception {
// #formatter:off
http
.headers().frameOptions().disable()
.and().logout()
.and().antMatcher("/**").authorizeRequests()
.antMatchers("/", "/login**", "/index.html", "/home.html").permitAll()
.anyRequest().authenticated()
.and().exceptionHandling().authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/"))
.and().logout().logoutSuccessUrl("/").permitAll()
.and().csrf().csrfTokenRepository(csrfTokenRepository())
.and().addFilterAfter(csrfHeaderFilter(), CsrfFilter.class)
.addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
// #formatter:on
}
private Filter csrfHeaderFilter() {
return new OncePerRequestFilter() {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
if (csrf != null) {
Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
String token = csrf.getToken();
if (cookie == null || token != null && !token.equals(cookie.getValue())) {
cookie = new Cookie("XSRF-TOKEN", token);
cookie.setPath("/");
response.addCookie(cookie);
}
}
filterChain.doFilter(request, response);
}
};
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
#Bean
public FilterRegistrationBean oauth2ClientFilterRegistration(OAuth2ClientContextFilter filter) {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(filter);
registration.setOrder(-100);
return registration;
}
#Bean
#ConfigurationProperties("ok")
ClientResources ok() {
return new ClientResources();
}
private Filter ssoFilter() {
CompositeFilter filter = new CompositeFilter();
List<Filter> filters = new ArrayList<>();
filters.add(ssoFilter(ok(), "/login/ok"));
filter.setFilters(filters);
return filter;
}
private Filter ssoFilter(ClientResources client, String path) {
OAuth2ClientAuthenticationProcessingFilter clientFilter = new OAuth2ClientAuthenticationProcessingFilter(path);
OAuth2RestTemplate clientTemplate = new OAuth2RestTemplate(client.getClient(), oauth2ClientContext);
clientFilter.setRestTemplate(clientTemplate);
OkUsersClient okUsersClient = new OkUsersClient(client.getResource().getUserInfoUri(), okClientPublicKey,
client.getClient().getClientSecret(), clientTemplate);
clientFilter.setTokenServices(new OkUserInfoTokenServices(okUsersClient, client.getClient().getClientId()));
clientFilter.setAuthenticationSuccessHandler(new UrlParameterAuthenticationHandler());
return clientFilter;
}
class UrlParameterAuthenticationHandler extends SimpleUrlAuthenticationSuccessHandler {
#Override
protected void handle(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
String targetUrl = determineTargetUrl(request, response);
if (response.isCommitted()) {
logger.debug("Response has already been committed. Unable to redirect to " + targetUrl);
return;
}
String queryString = HttpUtils.removeParams(request.getQueryString(), "state", "code");
targetUrl = !StringUtils.isEmpty(queryString) ? targetUrl + "?" + queryString : targetUrl;
getRedirectStrategy().sendRedirect(request, response, targetUrl);
}
}
class ClientResources {
private OAuth2ProtectedResourceDetails client = new AuthorizationCodeResourceDetails();
private ResourceServerProperties resource = new ResourceServerProperties();
public OAuth2ProtectedResourceDetails getClient() {
return client;
}
public ResourceServerProperties getResource() {
return resource;
}
}
}
application.yml:
server:
port: 8443
ssl:
key-store: keystore.p12
key-store-password: ***
keyStoreType: PKCS12
keyAlias: tomcat
spring:
aop:
proxy-target-class: true
ok:
client:
accessTokenUri: https://api.ok.ru/oauth/token.do
userAuthorizationUri: https://connect.ok.ru/oauth/authorize
clientId: ***
clientSecret: ***
publicKey: ***
authenticationScheme: query
clientAuthenticationScheme: form
resource:
userInfoUri: https://api.ok.ru/fb.do
logging:
file: application.log
level:
org.springframework: INFO
If you have Spring Security (you have, because of EnableOAuth2Client) in your project and don't specify a user and a password Spring Boot creates at least a secure password for you (you might want to read more in the manual)
)
If Spring Security is on the classpath then web applications will be
secure by default with ‘basic’ authentication on all HTTP endpoints.
To add method-level security to a web application you can also add
#EnableGlobalMethodSecurity with your desired settings. Additional
information can be found in the Spring Security Reference.
The default AuthenticationManager has a single user (‘user’ username
and random password, printed at INFO level when the application starts
up)
Using default security password: 78fa095d-3f4c-48b1-ad50-e24c31d5cf35
You should set these values in application.properties to avoid it:
security.user.name=...
security.user.password=...
security.user.role=...
Converted to your application.yml it will look like:
security:
user:
name: ...
password: ...
role: ...
Related
I'm making an Angular application as the frontend with a Springboot backend. I have set up SpringSecurity to handle logins and if I try it using Postman everything works, but when I try it using Angulars login, the "request.getParameter" calls always return me "null". I have tried changing it in several ways but the result is always the same.
The successful login return information about the user and a token.
Here is the Java part:
#Configuration
#EnableWebSecurity
#ComponentScan
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Lazy
#Autowired
CurrentUserDetailsServiceImpl userDetailsService;
#Autowired
TokenAuthenticationService tokenAuthService;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers().cacheControl().disable();
http
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http
.headers().xssProtection();
http
.exceptionHandling().and()
.anonymous().and()
.servletApi().and()
.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/auth/**").permitAll()
.anyRequest().authenticated().and()
.addFilterBefore(
new LoginFilter("/auth/login", authenticationManager(), tokenAuthService),
UsernamePasswordAuthenticationFilter.class)
// Custom Token based authentication based on the header previously given to the
// client
.addFilterBefore(new JWTFilter(tokenAuthService), UsernamePasswordAuthenticationFilter.class);
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(new BCryptPasswordEncoder());
}
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
// Allow anonymous resource requests
.antMatchers("/favicon.ico");
}
}
The LoginFilter does quite some things, but this is the minimum:
public class LoginFilter extends AbstractAuthenticationProcessingFilter {
private TokenAuthenticationService tokenAuthenticationService;
public LoginFilter(String urlMapping, AuthenticationManager authenticationManager, TokenAuthenticationService tokenAuthenticationService) {
super(new AntPathRequestMatcher(urlMapping));
setAuthenticationManager(authenticationManager);
this.tokenAuthenticationService = tokenAuthenticationService;
}
#Override
#Transactional
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException, IOException, ServletException {
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println("USERNAME: " + username + " - PASSWORD: " + password);
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
Authentication authentication) throws IOException, ServletException {
CurrentUser loggedUser = (CurrentUser) authentication.getPrincipal();
...
}
}
Finally, the Angular form does some validations and calls to a service:
#Injectable({
providedIn: 'root'
})
export class LoginService {
apiUrl: string = environment.API_URL;
constructor(private http: HttpClient) {}
login(data: LoginInterface): Observable<LoginResult> {
const formData: string =
'username=' + data.username + '&password=' + data.password;
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/x-www-form-urlencoded'
})
};
return this.http.post<LoginResult>(
this.apiUrl + '/auth/login',
formData,
httpOptions
);
}
}
What am I doing wrong? Why is it working with Postman?
Thanks!
Edit: As requested, here are the console details for the call in Chrome
Headers:
Body:
Postman headers:
Postman data:
And here is Eclipse showing the null value that arrived:
Thanks!
You can probably do it by using HttpParams as the request body:
login(data: LoginInterface): Observable<LoginResult> {
const params = new HttpParams({
fromObject: {
username: data.username,
password: data.password,
},
});
return this.http.post<LoginResult>(this.apiUrl + '/auth/login', params, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
});
}
I'm trying to build a REST API with Spring Boot and Spring Security but I have run into an issue where any request to the /login endpoint is blocked because of CORS and I can't figure out how to allow it.
Here's what I get when I inspect the network tab of my developper tools whenever I send a login request in my frontend application:
Here's my SecurityConfig.java file (I've omitted imports for brevity):
#EnableWebSecurity(debug = true)
#RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final AuthenticationUserDetailService authenticationUserDetailService;
private final PasswordEncoder passwordEncoder;
#Value("${jwt.secret}")
private String jwtSecret;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.cors();
http.authorizeRequests().antMatchers("/login").permitAll();
http.authorizeRequests().antMatchers("/").permitAll();
http.authorizeRequests().antMatchers("/api/teachers/**").hasAuthority("TEACHER");
http.authorizeRequests().antMatchers("/api/students/**").hasAuthority("STUDENT");
http.authorizeRequests().antMatchers("/api/**").hasAuthority("ADMIN");
http.authorizeRequests().anyRequest().authenticated();
//http.authorizeRequests().anyRequest().permitAll();
http.addFilter(new JwtAuthenticationFilter(authenticationManager(), jwtSecret));
http.addFilter(new JwtAuthorizationFilter(authenticationManager(), jwtSecret));
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(authenticationUserDetailService).passwordEncoder(passwordEncoder);
}
}
Here's my JwtAuthenticationFilter.java file:
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private final AuthenticationManager authenticationManager;
private final String jwtSecret;
public JwtAuthenticationFilter(AuthenticationManager authenticationManager, String jwtSecret) {
this.authenticationManager = authenticationManager;
this.jwtSecret = jwtSecret;
setFilterProcessesUrl("/login");
}
#Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
try {
LoginRequest credentials = new ObjectMapper()
.readValue(request.getInputStream(), LoginRequest.class);
return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
credentials.getUsername(),
credentials.getPassword(),
new ArrayList<>())
);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
User user = (User) authResult.getPrincipal();
String token = Jwts.builder()
.signWith(SignatureAlgorithm.HS512, jwtSecret.getBytes())
.claim("role", authResult.getAuthorities().iterator().next().getAuthority())
.setSubject(user.getUsername())
.setExpiration(new Date(System.currentTimeMillis() + 24 * 3600 * 1000))
.compact();
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().write("{\"token\":\"" + token + "\"}");
}
}
I have tried every solution I have found online and I'm out of ideas. How can I authorize CORS from any source for my /login endpoint ?
Thanks a lot!
You have to provide a Bean of type CorsConfigurationSource and tell Spring Security to use that configuration source in the CorsFilter, and place it before the authentication and authorization filters.
First, define the CorsConfigurationSource Bean:
#Bean
CorsConfigurationSource corsConfigurationSource() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.addAllowedOrigin("http://localhost:3000");
source.registerCorsConfiguration("/**", config);
return source;
}
Then, tell Spring Security to configure CORS with defaults:
#Override
protected void configure(HttpSecurity http) throws Exception {
...
http.cors(Customizer.withDefaults());
...
}
I'm using LDAP authentication provider (active directory) + JWT authorization filter.
I have my custom user object implementing UserDetails, also my user service extends UserDetailsService. But when I do:
Usuario principal = (Usuario) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
Principal is just a string (the username), not my user object.
This is my configuration:
SecurityConfig:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final LdapProperties ldapProperties;
private final LdapUserMapper ldapUserMapper;
private final UserService userService;
public SecurityConfig(LdapProperties ldapProperties, LdapUserMapper ldapUserMapper, UserService userService) {
this.ldapProperties = ldapProperties;
this.ldapUserMapper = ldapUserMapper;
this.userService = userService;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
// Entry points
http.authorizeRequests()
.antMatchers(HttpMethod.POST, "/login").permitAll()
.antMatchers(HttpMethod.GET, "/v2/api-docs",
"/configuration/ui",
"/swagger-resources",
"/configuration/security",
"/swagger-ui.html",
"/webjars/**",
"/swagger-resources/**",
"/swagger-ui.html").permitAll()
//TODO review
.anyRequest().authenticated();
// JwtWebSecurityConfigurer... TODO ?
// Filters
http.addFilter(new AuthenticationFilter(authenticationManager())); // ldap
http.addFilter(new AuthorizationFilter(authenticationManager())); // jwt
http.cors();
http.csrf().disable();
// No session will be created or used by spring security
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// Need to provide Authorization header
http.httpBasic();
}
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(ldapAuthenticationProvider());
auth.userDetailsService(userService);
}
#Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration corsConfiguration = new CorsConfiguration().applyPermitDefaultValues();
corsConfiguration.setAllowedMethods(Arrays.asList(CorsConfiguration.ALL));
//TODO configure properly
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", corsConfiguration);
return source;
}
#Bean
public AbstractLdapAuthenticationProvider ldapAuthenticationProvider() {
String urls = "";
for (String url : ldapProperties.getUrls()) {
urls += url + " ";
}
urls = urls.trim();
ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(
ldapProperties.getBaseEnvironment().get("domain"),
urls,
ldapProperties.getBase()
);
provider.setUserDetailsContextMapper(ldapUserMapper);
provider.setConvertSubErrorCodesToExceptions(true);
// comment to connect as anonymous
provider.authenticate(
new UsernamePasswordAuthenticationToken(ldapProperties.getUsername(), ldapProperties.getPassword())
);
return provider;
}
}
LdapUserMapper:
#Component
public class LdapUserMapper implements UserDetailsContextMapper {
private final UserService userService;
#Autowired
public LdapUserMapper(UserService userService) {
this.userService = userService;
}
#Override
public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<? extends GrantedAuthority> authorities) {
Usuario result = (Usuario) userService.loadUserByUsername(username);
//TODO compare roles ? set bloqueado ? ...
return result;
}
#Override
public void mapUserToContext(UserDetails userDetails, DirContextAdapter dirContextAdapter) {
}
}
It was my authorization filter.
#Override
protected void doFilterInternal(HttpServletRequest req,
HttpServletResponse res,
FilterChain chain) throws IOException, ServletException {
String token = req.getHeader("Authorization");
if (token != null && token.startsWith("Bearer ")) {
token = token.replace("Bearer ", "");
Authentication authentication = getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
chain.doFilter(req, res);
}
private UsernamePasswordAuthenticationToken getAuthentication(final String token) {
try {
DecodedJWT decodedToken = JWT.require(Algorithm.HMAC512(jwtSecret)).build().verify(token);
String username = decodedToken.getSubject();
return new UsernamePasswordAuthenticationToken(username , null, new ArrayList<>());
} catch (JWTVerificationException ex) {
log.error(ex.getMessage());
}
return null;
}
I wasn't aware that I only was passing the username as the Principal object. So I changed it to this:
Usuario usuario = (Usuario) userService.loadUserByUsername(decodedToken.getSubject());
I also removed
auth.userDetailsService(userService);
From AuthenticationManagerBuilder config. That was wrong. My auth provider is LDAP, not the DB.
I created a custom filter that fetches a token and then populates the authentication object with the token-related roles
#Component
public class TokenAuthenticationFilter extends GenericFilterBean {
#Autowired
private IAMUserDAO iamUserDAO;
#Autowired
CDBUserProfileDao cdbUserProfileDao;
#Autowired
IAMOAuth2Dao iamOAuth2DAO;
final static Logger logger = Logger.getLogger(TokenAuthenticationFilter.class.getCanonicalName());
#Override
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
throws IOException, ServletException {
final HttpServletRequest httpRequest = (HttpServletRequest) request;
final String accessToken = httpRequest.getHeader("Authorization");
logger.info("Request with token " + accessToken + " intercepted for rba purpose");
if (!StringUtil.isBlank(accessToken)) {
ResponseEntity<String> tokenResponse = Utils.validateAccessToken(httpRequest, iamOAuth2DAO);
if (tokenResponse.getStatusCode().equals(HttpStatus.OK)) {
try {
UserProfiles userProfileResponse = cdbUserProfileDao.getCDBUserProfile(tokenResponse.getBody());
if (userProfileResponse != null) {
String action = iamUserDAO.getFbiFederatedAction(userProfileResponse.getEntid(),
userProfileResponse.getRoles().getRole());
if (!StringUtil.isBlank(action)) {
List<GrantedAuthority> authorities = Arrays.asList(action.split(",")).stream()
.map(s -> new SimpleGrantedAuthority(s)).collect(Collectors.toList());
final User user = new User("", "", true, true, true, true, authorities);
final UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
user, null, user.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
} catch (Exception e) {
logger.error("rba processing encounter an error " + e.getMessage());
}
}
}
logger.info("Exiting rba filter with token " + accessToken);
chain.doFilter(request, response);
}
}
I then added that filter to a springsecuritycontext as followed:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
#Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new TokenAuthenticationFilter());
registrationBean.setEnabled(false);
return registrationBean;
}
#Override
protected void configure(final HttpSecurity http) throws Exception {
// Implementing Token based authentication in this filter
http.addFilterBefore(new TokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
http.authorizeRequests().antMatchers("/calendar/search", "/calendar/v2/search")
.access("hasRole('use-calendar') or hasRole('admin')").anyRequest().authenticated();
}
}
The application existed already and I just try to add the spring security layer. The spring security version is 4.2.3. After days trying to implement this, the TokenAuthenticationFilter is not loaded and consequently no request is filtered. Please help.
Since the application already existed before adding the Spring Security layer, I had to add the filter in the web.xml file in the below manner:
<filter>
<filter-name>tokenAuthenticationFilter</filter-name>
<filter-class>com.mycompany.authenticateb.config.TokenAuthenticationFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>tokenAuthenticationFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
I am developing a web service including three web servers with spring boot:
1. localhost:8080 - ui
2. localhost:9999 - uaa (authserver)
3. localhost:9000 - ressource
I took this example repository https://github.com/spring-guides/tut-spring-security-and-angular-js/tree/master/oauth2 and modified it with a UserDetailsService and a custom authenticationSuccessHandler / authenticationFailureHandler for the login process.
I would like to have my login page at the localhost:8080 and make a ajax / angularjs request to the localhost:9999 to login. This works fine but I do not get the jsessionid issued by the uaa server in the response header and therefore I can not make any secured requests.
How do I have to modify my authserver to send the jsessionid as a cookie back to my ui server?
This is the response header, if I would have the template on the authserver like the example repository and make the request:
And this is the response header, if I make the request by the localhost:8080 to the authserver:
Source Code:
-Authserver (localhost:9999)
#Configuration
#EnableAuthorizationServer
public class OAuth2AuthorizationConfig extends AuthorizationServerConfigurerAdapter {
#Autowired
private AuthenticationManager authenticationManager;
#Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
KeyPair keyPair = new KeyStoreKeyFactory(new ClassPathResource("keystore.jks"), "foobar".toCharArray())
.getKeyPair("test");
converter.setKeyPair(keyPair);
return converter;
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
// #formatter:off
endpoints
.authenticationManager(authenticationManager)
.accessTokenConverter(jwtAccessTokenConverter());
// #formatter:on
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// #formatter:off
clients.inMemory()
.withClient("acme").secret("acmesecret")
.authorizedGrantTypes("authorization_code", "refresh_token", "password")
.scopes("openid")
.autoApprove(true);
// #formatter:on
}
}
#Configuration
#EnableWebSecurity
#Order(-20)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private RESTAuthenticationEntryPoint authenticationEntryPoint;
#Autowired
private RESTAuthenticationFailureHandler authenticationFailureHandler;
#Autowired
private RESTAuthenticationSuccessHandler authenticationSuccessHandler;
public WebSecurityConfig(){
super();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
// #formatter:off
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/signup", "/forgotPassword", "/user/updatePassword**", "/user/registration", "/user/registrationConfirm**", "/user/resendRegistrationToken**", "/user/resetPassword**", "/user/changePassword**", "/user/savePassword").permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
.and()
.formLogin().loginPage("/login").successHandler(authenticationSuccessHandler).failureHandler(authenticationFailureHandler).permitAll()
.and()
.requestMatchers().antMatchers("/login**", "/signup", "/forgotPassword", "/user/updatePassword**", "/user/registration", "/user/registrationConfirm**", "/user/resendRegistrationToken**", "/user/resetPassword**", "/user/changePassword**", "/user/savePassword", "/oauth/authorize", "/oauth/confirm_access");
// #formatter:on
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authProvider());
}
//Beans
#Bean
public DaoAuthenticationProvider authProvider() {
final DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(encoder());
return authProvider;
}
#Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder(11);
}
}
#Component
public class RESTAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
#Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
clearAuthenticationAttributes(request);
}
}
#Component
public class RESTAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
#Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
super.onAuthenticationFailure(request, response, exception);
}
}
#Component
public class RESTAuthenticationEntryPoint implements AuthenticationEntryPoint {
#Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
}
-ui-Server (localhost:8080)
#Configuration
#Order(-20)
#EnableZuulProxy
#EnableOAuth2Sso
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
//#formatter:off
http
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/").deleteCookies("XSRF-TOKEN").deleteCookies("JSESSIONID").invalidateHttpSession(true)
.and()
.antMatcher("/**").authorizeRequests()
.antMatchers(
"/",
"/signin",
"/uaa/login",
"/pix/**").permitAll()
.anyRequest().authenticated()
.and()
.csrf().csrfTokenRepository(csrfTokenRepository())
.and()
.addFilterAfter(csrfHeaderFilter(), CsrfFilter.class);
//#formatter:on
}
private Filter csrfHeaderFilter() {
return new OncePerRequestFilter() {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
if (csrf != null) {
Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
String token = csrf.getToken();
if (cookie == null || token != null && !token.equals(cookie.getValue())) {
cookie = new Cookie("XSRF-TOKEN", token);
cookie.setPath("/");
response.addCookie(cookie);
}
}
filterChain.doFilter(request, response);
}
};
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
}
application.yml
server:
port: 8080
debug: true
spring:
aop:
proxy-target-class: true
security:
user:
password: none
oauth2:
client:
accessTokenUri: http://localhost:9999/uaa/oauth/token
userAuthorizationUri: http://localhost:9999/uaa/oauth/authorize
clientId: acme
clientSecret: acmesecret
resource:
jwt:
keyValue: |
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnGp/Q5lh0P8nPL21oMMrt2RrkT9AW5jgYwLfSUnJVc9G6uR3cXRRDCjHqWU5WYwivcF180A6CWp/ireQFFBNowgc5XaA0kPpzEtgsA5YsNX7iSnUibB004iBTfU9hZ2Rbsc8cWqynT0RyN4TP1RYVSeVKvMQk4GT1r7JCEC+TNu1ELmbNwMQyzKjsfBXyIOCFU/E94ktvsTZUHF4Oq44DBylCDsS1k7/sfZC2G5EU7Oz0mhG8+Uz6MSEQHtoIi6mc8u64Rwi3Z3tscuWG2ShtsUFuNSAFNkY7LkLn+/hxLCu2bNISMaESa8dG22CIMuIeRLVcAmEWEWH5EEforTg+QIDAQAB
-----END PUBLIC KEY-----
zuul:
routes:
resource:
path: /resource/**
url: http://localhost:9000/resource
user:
path: /uaa/**
url: http://localhost:9999/uaa
logging:
level:
org.springframework.security: DEBUG
signin.js
'use strict';
angular.module('loginUser').controller('LoginViewController', function($scope, $http) {
$scope.login = function() {
$http({
method: 'POST',
url: '/uaa/login',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
transformRequest: function(obj) {
var str = [];
for(var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
},
data: {"username": $scope.user.username, "password": $scope.user.password}
})
.success(function (data) {
console.log(data);
})
.error(function(data, status) {
console.log(data);
console.log(status);
});
}
});
angular.module('loginUser').run(function run($http, $cookies){
$http.defaults.headers.post['X-XSRF-TOKEN'] = $cookies['XSRF-TOKEN'];
$http.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
});