我主要关注https://www.youtube.com/watch?v=EoK5a99Bmjc&list=WL&index=12(摘要:https://netcrash.wordpress.com/2017/08/21/summary-of-josh-long-youtube-video-about-security-oauth/#comment-39,直到ResourceServer发挥作用)。
我已阅读Access sensitive Spring boot actuator endpoints via tokens in browser因为它接近我需要的内容,但我不一定需要浏览器而且该问题没有得到解答。
与教程相比,我将spring-boot-starter-actuator作为我的pom.xml中的依赖项。
我的 application.properties 如下所示:
logging.level=DEBUG
server.port=9191
endpoints.health.enabled=true
endpoints.health.sensitive=false
endpoints.shutdown.enabled=true
endpoints.shutdown.sensitive=true
management.contextPath: /manage
management.security.enabled=true
我的 AccountUserDetailsService 如下所示:
package com.divstar.particle.authservice.rest;
import java.text.MessageFormat;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
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;
@Service
public class AccountUserDetailsService implements UserDetailsService {
private final IAccountRepository accountRepository;
public AccountUserDetailsService(final IAccountRepository accountRepository) {
this.accountRepository = accountRepository;
}
@Override
public UserDetails loadUserByUsername(final String username) {
return accountRepository.findByUsername(username)
.map(account -> new User(account.getUsername(), account.getPassword(), account.isEnabled(),
account.isNonExpired(), account.isCredentialsNonExpired(), account.isNonLocked(),
AuthorityUtils.createAuthorityList("ROLE_ADMIN", "ROLE_USER", "ROLE_ACTUATOR")))
.orElseThrow(() -> new UsernameNotFoundException(
MessageFormat.format("Could not find the user {0}!", username)));
}
}
我添加了角色" ROLE_ACTUATOR ",因为它似乎是执行机构访问管理服务端点所需的内容。
主要应用类看起来很简单:
package com.divstar.particle.authservice;
import java.util.stream.Stream;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import com.divstar.particle.authservice.rest.Account;
import com.divstar.particle.authservice.rest.IAccountRepository;
@SpringBootApplication
public class Application {
@Bean
CommandLineRunner initUsers(final IAccountRepository userRepository) {
return args -> Stream.of("test,long", "blame,short", "pass,secure")
.map(tpl -> tpl.split(","))
.forEach(tpl -> userRepository.save(new Account(tpl[0], tpl[1], "sample@mail.com", true, true, true, true)));
}
public static void main(final String[] args) {
SpringApplication.run(Application.class, args);
}
}
IAccountRepository 扩展了JpaRepository并定义了" findByUsername",它返回Optional。
我的 AuthorizationServerConfigurationAdapter 如下所示:
package com.divstar.particle.authservice;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
@Configuration
@EnableAuthorizationServer
public class AuthServiceConfiguration extends AuthorizationServerConfigurerAdapter {
private final AuthenticationManager authenticationManager;
public AuthServiceConfiguration(final AuthenticationManager authenticationManager) {
super();
this.authenticationManager = authenticationManager;
}
@Override
public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("html5")
.secret("clientsecret")
.authorizedGrantTypes("password")
.scopes("openid");
}
@Override
public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
}
启动身份验证服务器后,我使用以下cURL命令获取令牌:
curl html5:clientsecret@localhost:9191/oauth/token -d grant_type=password -d username=test -d password=long
它返回access_token以及JSON回复中的更多信息。
然而,如果我尝试访问敏感端点(例如/ manage / shutdown),请执行以下操作:
curl -X POST -H"Authorization: bearer b8412762-af80-4b7d-9eb9-3fa472dd37c9" localhost:9191/manage/shutdown
我收到以下错误消息:
{"时间戳":1508029184236,"状态":401,"错误":"未授权""消息&# 34;:"全 访问它需要身份验证 资源""路径":" /管理/关机"}
我错过了什么/做错了什么?如果令牌有效(给定适当的权限/角色),我怎样才能让spring-boot执行器识别JWT并执行给定的敏感端点?
答案 0 :(得分:0)
根据您分享的信息,您实际上并没有告诉Spring使用您的自定义UserDetailsService。为了做到这一点,你必须有一个扩展WebSecurityConfigurerAdapter的类,然后覆盖configure(AuthenticationManagerBuilder auth)
方法,如下所示:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserDetailsService);
}
有关OAuth2和自定义UserDetailsService的更多信息,请参阅此处:https://stackoverflow.com/a/43245998/1320627
确保正确配置用户详细信息服务的最简单方法是添加REST端点,使用身份验证进行保护,然后尝试点击它。