我正在尝试将spring boot与OAuth2集成.通过以下https://github.com/royclarkson/spring-rest-service-oauth,我能够使用InMemoryStore来处理令牌.但是当我尝试使用JdbcTokenStore和postgres数据库实现它时,我得到了错误
Handling error: BadSqlGrammarException, PreparedStatementCallback; bad SQL grammar [select token_id, token from oauth_access_token where authentication_id = ?]; nested exception is org.postgresql.util.PSQLException: ERROR: relation "oauth_access_token" does not exist
我检查了我的数据库,表存在.
网络安全配置
@Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { private static PasswordEncoder encoder; @Autowired private CustomUserDetailsService userDetailsService; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); } @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Bean public PasswordEncoder passwordEncoder() { if(encoder == null) { encoder = new BCryptPasswordEncoder(); } return encoder; } }
Oauth2Config
@Configuration public class OAuth2ServerConfiguration { private static final String RESOURCE_ID = "restservice"; @Configuration @EnableResourceServer protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { @Autowired private TokenStore tokenStore; @Override public void configure(ResourceServerSecurityConfigurer resources) { // @formatter:off resources .tokenStore(tokenStore) .resourceId(RESOURCE_ID); // @formatter:on } @Override public void configure(HttpSecurity http) throws Exception { // @formatter:off http .authorizeRequests() .antMatchers("/users").hasRole("ADMIN") .antMatchers("/userAccounts/create").permitAll() .antMatchers("/greeting").authenticated(); // @formatter:on } } @Configuration @EnableAuthorizationServer protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { @Autowired DataSource dataSource; @Bean public JdbcTokenStore tokenStore() { return new JdbcTokenStore(dataSource); } private static PasswordEncoder encoder; @Autowired @Qualifier("authenticationManagerBean") private AuthenticationManager authenticationManager; @Autowired private CustomUserDetailsService userDetailsService; @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { // @formatter:off endpoints //.tokenStore(new InMemoryTokenStore()) .tokenStore(tokenStore()) .authenticationManager(this.authenticationManager) .userDetailsService(userDetailsService); // @formatter:on } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { // @formatter:off clients //.inMemory() .jdbc(dataSource) .passwordEncoder(passwordEncoder()); //.withClient("clientapp") //.authorizedGrantTypes("password", "refresh_token") //.authorities("USER") //.scopes("read", "write") //.resourceIds(RESOURCE_ID) //.secret("123456"); // @formatter:on } @Bean @Primary public DefaultTokenServices tokenServices() { DefaultTokenServices tokenServices = new DefaultTokenServices(); tokenServices.setSupportRefreshToken(true); tokenServices.setTokenStore(tokenStore()); //tokenServices.setTokenStore(new InMemoryTokenStore()); return tokenServices; } @Bean public PasswordEncoder passwordEncoder() { if(encoder == null) { encoder = new BCryptPasswordEncoder(); } return encoder; } } }
CustomUserDetailsService
@Service public class CustomUserDetailsService implements UserDetailsService { private AccountInfoRepository accountInfoRepository; @Autowired public CustomUserDetailsService(AccountInfoRepository accountInfoRepository) { this.accountInfoRepository = accountInfoRepository; } @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { AccountInfo user = accountInfoRepository.findByUsername(username); System.out.println("USER IS "+user); if (user == null) { throw new UsernameNotFoundException(String.format("User %s does not exist!", username)); } return new UserRepositoryUserDetails(user); } private final static class UserRepositoryUserDetails extends AccountInfo implements UserDetails,Serializable { private static final long serialVersionUID = 1L; private UserRepositoryUserDetails(AccountInfo 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 true; } } }
application.properties
spring.jpa.database=POSTGRESQL spring.datasource.platform=postgres spring.jpa.show-sql=true spring.jpa.properties.hibernate.default_schema=test spring.jpa.hibernate.ddl-auto=none spring.datasource.driver-class-name=org.postgresql.Driver spring.datasource.url=jdbc:postgresql://localhost:5432/test spring.datasource.username=postgres spring.datasource.password=postgres spring.datasource.schema=test spring.profiles.active=dev #Application specific security.oauth2.client.client-id=clientapp security.oauth2.client.client-secret=123456 security.oauth2.client.authorized-grant-types=password,refresh_token security.oauth2.client.authorities=ROLE_USER security.oauth2.client.scope=read,write security.oauth2.client.resource-ids=restservice security.oauth2.client.access-token-validity-seconds=1800
用户对象
@JsonIgnoreProperties(ignoreUnknown = true) @Entity @Table(name = "account_info") public class AccountInfo implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "account_id") Integer accountId; @Column(name = "account_name") String accountName; @Column(name = "address_line_1") String addressLine1; @Column(name = "address_line_2") String addressLine2; String city; String state; String country; @NotEmpty @Column(unique = true, nullable = false) String username; @NotEmpty String password; String email; @JsonIgnore @ManyToMany(fetch = FetchType.EAGER) @JoinTable(name = "user_role", joinColumns = { @JoinColumn(name = "user_id") }, inverseJoinColumns = { @JoinColumn(name = "role_id") }) private Setroles = new HashSet<>(); public AccountInfo() { } public AccountInfo(AccountInfo accountInfo) { this.accountId = accountInfo.getAccountId(); this.accountName = accountInfo.getAccountName(); this.username = accountInfo.getUsername(); this.password = accountInfo.getPassword(); this.roles = accountInfo.getRoles(); } public boolean isSetup() { return isSetup; } public void setSetup(boolean isSetup) { this.isSetup = isSetup; } public Integer getAccountId() { return accountId; } public void setAccountId(Integer accountId) { this.accountId = accountId; } public String getAccountName() { return accountName; } public void setAccountName(String accountName) { this.accountName = accountName; } public String getAddressLine1() { return addressLine1; } public void setAddressLine1(String addressLine1) { this.addressLine1 = addressLine1; } public String getAddressLine2() { return addressLine2; } public void setAddressLine2(String addressLine2) { this.addressLine2 = addressLine2; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Set getRoles() { return roles; } public void setRoles(Set roles) { this.roles = roles; }
这就是我创建用户的方式
account.setPassword(new BCryptPasswordEncoder().encode(account.getPassword())); Setroles = new HashSet<>(); roles.add(new Role("ROLE_USER",1)); account.setRoles(roles); AccountInfo savedAccount=accountInfoRepository.save(account);
OAuth2表
CREATE TABLE oauth_client_details ( client_id VARCHAR(256) PRIMARY KEY, resource_ids VARCHAR(256), client_secret VARCHAR(256), scope VARCHAR(256), authorized_grant_types VARCHAR(256), web_server_redirect_uri VARCHAR(256), authorities VARCHAR(256), access_token_validity INTEGER, refresh_token_validity INTEGER, additional_information VARCHAR(4096), autoapprove VARCHAR(256) ); ALTER TABLE oauth_client_details OWNER TO postgres; CREATE TABLE oauth_client_token ( token_id VARCHAR(256), token bytea, authentication_id VARCHAR(256), user_name VARCHAR(256), client_id VARCHAR(256) ); ALTER TABLE oauth_client_token OWNER TO postgres; CREATE TABLE oauth_access_token ( token_id VARCHAR(256), token bytea, authentication_id VARCHAR(256), user_name VARCHAR(256), client_id VARCHAR(256), authentication bytea, refresh_token VARCHAR(256) ); ALTER TABLE oauth_access_token OWNER TO postgres; CREATE TABLE oauth_refresh_token ( token_id VARCHAR(256), token bytea, authentication bytea ); ALTER TABLE oauth_refresh_token OWNER TO postgres; CREATE TABLE oauth_code ( code VARCHAR(256), authentication bytea ); ALTER TABLE oauth_code OWNER TO postgres;
Dave Syer.. 5
OAuth2 JDBC连接器不了解架构。您需要将默认架构添加到数据库中用户的配置文件中,或者在URL中明确指定它。像这样的东西:jdbc:postgresql://localhost:5432/test?currentSchema=test
。
OAuth2 JDBC连接器不了解架构。您需要将默认架构添加到数据库中用户的配置文件中,或者在URL中明确指定它。像这样的东西:jdbc:postgresql://localhost:5432/test?currentSchema=test
。