我刚刚开始使用OAuth和Spring Boot,并做了一个基本的应用程序来看它的实际效果。
这是我的MySQL架构:
def signup
if request.post?
puts "SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSs"
@user = User.new(user_params)
if @user.save
flash[:notice] = t("flash.signup")
#Weiterleitung nach erfolgreichem Anlegen
redirect_to :controller => :startsites, :action => "index"
end
else
@user = User.new
end
end
数据:
CREATE TABLE `role` (
`id` int(20) NOT NULL,
`role` varchar(50) NOT NULL,
PRIMARY KEY (`role`)
)
CREATE TABLE `user` (
`name` varchar(255) DEFAULT NULL,
`username` varchar(50) NOT NULL,
`email` varchar(50) DEFAULT NULL,
`password` varchar(500) DEFAULT NULL,
`enabled` tinyint(1) DEFAULT '0',
`activationkey` varchar(50) DEFAULT NULL,
`resetpasswordkey` varchar(50) DEFAULT NULL,
PRIMARY KEY (`username`),
KEY `name` (`name`)
)
CREATE TABLE `user_role` (
`username` varchar(50) NOT NULL,
`role` varchar(50) NOT NULL,
`id` int(20) NOT NULL,
PRIMARY KEY (`id`),
KEY `USER_FK` (`username`),
KEY `ROLE_FK` (`role`),
CONSTRAINT `ROLE_FK` FOREIGN KEY (`role`) REFERENCES `role` (`role`),
CONSTRAINT `USER_FK` FOREIGN KEY (`username`) REFERENCES `user` (`name`)
)
代码:
INSERT INTO `role` VALUES ('1', 'ROLE_ADMIN');
INSERT INTO `role` VALUES ('3', 'ROLE_GUEST');
INSERT INTO `role` VALUES ('2', 'ROLE_USER');
INSERT INTO `user` VALUES ('Leonardo', 'leonardo', 'leonardo.mora@datys.cu', 'admin', '1', null, null);
INSERT INTO `user_role` VALUES ('leonardo', 'ROLE_ADMIN', '0');
OAuth配置:
/**
* My CustomUserDetailService
*/
@Service
public class CustomUserDetailService implements UserDetailsService {
private final UserRepository userRepository;
@Autowired
public CustomUserDetailService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException(String.format("User %s does not exist!", username));
}
return new UserRepositoryUserDetails(user);
}
private static class UserRepositoryUserDetails extends User implements UserDetails {
private UserRepositoryUserDetails(User user) {
super(user);
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return getRoles();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return getEnabled();
}
}
}
网络安全配置:
@Configuration
public class Oauth2JdbcSample extends WebSecurityConfigurerAdapter {
private static final String RESOURCE_ID = "cenergy";
/**
* Esta clase es para configurar el servidor de recursos
*
* @author leonardo.mora
*/
@Configuration
@EnableResourceServer
protected static class ResourceServer extends ResourceServerConfigurerAdapter {
@Override
public void configure(ResourceServerSecurityConfigurer resources)
throws Exception {
resources
.resourceId(RESOURCE_ID);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/users")
.authenticated();
}
}
/**
* Esta clase es para configurar el servidor de autorizacion
*
* @author leonardo.mora
*/
@Configuration
@EnableAuthorizationServer
protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter {
private TokenStore tokenStore = new InMemoryTokenStore();
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private CustomUserDetailService userDetailsService;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints.tokenStore(this.tokenStore)
.authenticationManager(this.authenticationManager)
.userDetailsService(this.userDetailsService);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// @formatter:off
clients.inMemory()
.withClient("cenergy-client")
.authorizedGrantTypes("password")
.authorities("ROLE_ADMIN")
.scopes("read", "write")
.resourceIds(RESOURCE_ID)
.secret("123456")
.accessTokenValiditySeconds(300);
// @formatter:on
}
@Bean
@Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setSupportRefreshToken(true);
tokenServices.setTokenStore(this.tokenStore);
return tokenServices;
}
}
}
这是我的访问令牌请求:
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().csrfTokenRepository(csrfTokenRepository());
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setSessionAttributeName("_csrf");
return repository;
}
}
给了我错误:
curl -v -H "Content-Type: application/json" \
cenergy-client:123456@localhost:9191/api/oauth/token \
-d grant_type=password -d username=leonardo -d password=admin
有什么问题?
答案 0 :(得分:1)
对令牌端点的请求需要将其正文格式设置为application/x-www-form-urlencoded
而不是application/json
:
curl -v -H "Content-Type: application/x-www-form-urlencoded" \
cenergy-client:123456@localhost:9191/api/oauth/token \
-d grant_type=password -d username=leonardo -d password=admin
这是在OAuth2规范中定义的(具体在Section 4.3.中的密码授权):
4.3.2。访问令牌请求
客户端使用。向令牌端点[...]发出请求 每个Appendix B的“application / x-www-form-urlencoded”格式 HTTP请求实体中的UTF-8字符编码: