private static final Logger LOGGER = LoggerFactory.getLogger(OAuth2AuthorizationServerConfig.class);
@Value("${config.oauth2.privateKey}")
private String privateKey;
@Value("${config.oauth2.publicKey}")
private String publicKey;
@Autowired
private AuthenticationManager authenticationManager;
@Bean
public JwtAccessTokenConverter tokenEnhancer() {
LOGGER.info("Initializing JWT with public key:\n" + publicKey);
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(privateKey);
converter.setVerifierKey(publicKey);
return converter;
}
@Bean
public JwtTokenStore tokenStore() {
return new JwtTokenStore(tokenEnhancer());
}
/**
* Defines the security constraints on the token endpoints /oauth/token_key and /oauth/check_token
* Client credentials are required to access the endpoints
*
* @param oauthServer
* @throws Exception
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer
.tokenKeyAccess("isAnonymous() || hasRole('ROLE_TRUSTED_CLIENT')") // permitAll()
.checkTokenAccess("hasRole('TRUSTED_CLIENT')"); // isAuthenticated()
// oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()"); // 另外一种写法!
}
/**
* Defines the authorization and token endpoints and the token services
*
* @param endpoints
* @throws Exception
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
// Which authenticationManager should be used for the password grant
// If not provided, ResourceOwnerPasswordTokenGranter is not configured
.authenticationManager(authenticationManager)
// Use JwtTokenStore and our jwtAccessTokenConverter
.tokenStore(tokenStore())
.accessTokenConverter(tokenEnhancer())
;
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
// Confidential client where client secret can be kept safe (e.g. server side)
.withClient("confidential").secret("secret")
.authorizedGrantTypes("client_credentials", "authorization_code", "refresh_token")
.scopes("read", "write")
.redirectUris("http://192.168.1.99:8080/")
.and()
// Public client where client secret is vulnerable (e.g. mobile apps, browsers)
.withClient("public") // No secret!
.authorizedGrantTypes("client_credentials", "implicit")
.scopes("read")
.redirectUris("http://192.168.1.99:8080/")
.and()
// Trusted client: similar to confidential client but also allowed to handle user password
.withClient("trusted").secret("secret")
.authorities("ROLE_TRUSTED_CLIENT")
.authorizedGrantTypes("client_credentials", "password", "authorization_code", "refresh_token")
.scopes("read", "write")
.redirectUris("http://192.168.1.99:8080/")
;
}
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/", "/oauth/**", "/respond/**", "/html5shiv/**", "/images/**", "/css/**", "/js/**", "/jquery/**", "/bootstrap-3.3.6/**", "/angularjs/**").permitAll()
.antMatchers("/users/**").hasAuthority("ADMIN")
.anyRequest().fullyAuthenticated()
.and()
.formLogin()
.loginPage("/login")
.failureUrl("/login?error")
.usernameParameter("email")
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.deleteCookies("remember-me")
.logoutSuccessUrl("/")
.permitAll()
.and()
.rememberMe();
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(new BCryptPasswordEncoder());
}