Oauth2如何使用密码策略完成授权?
一、导入相关依赖
<!-- oauth2相关依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.3.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 数据库访问相关依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<!-- 测试相关依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
server:
port: 8092
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/token?serverTimezone=Asia/Shanghai&useSSL=false
username: root
password: 123456
jpa:
show-sql: true
hibernate:
ddl-auto: update
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
database: mysql
二、项目结构
三、oauth2的配置类
3.1、AuthorizationServerConfig(认证服务器)
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private DomainUserDetailsService userDetailsService;
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
super.configure(security);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory().withClient("client")
.secret(passwordEncoder.encode("client"))
.accessTokenValiditySeconds(2*60*60)
.authorizedGrantTypes(new String[]{"refresh_token", "password"})
.scopes( "all");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints){
endpoints
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
}
3.2、ResourceServerConfigurer (资源服务器)
@Configuration
@EnableResourceServer
public class ResourceServerConfigurer extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(Constant.IGNORE_PATHS
.toArray(new String[Constant.IGNORE_PATHS.size()])
).permitAll()
.anyRequest().authenticated()
.and()
.httpBasic().and().csrf().disable();
}
}
3.3、SecurityConfig (开启WebSercurity功能)
package com.yonyou.oauth.config;
import com.yonyou.oauth.DomainUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.client.RestTemplate;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
3.4、Constant (定义一些可忽略授权的API或路径)
public class Constant {
public static final List<String> IGNORE_PATHS;
static {
IGNORE_PATHS = new ArrayList<>();
IGNORE_PATHS.add("/v2/api-docs");
IGNORE_PATHS.add("/swagger-ui.html");
IGNORE_PATHS.add("/webjars/**");
}
}
四、密码策略的验证
DomainUserDetailsService 类
@Service
public class DomainUserDetailsService implements UserDetailsService {
@Autowired
private AccountService accountService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
String password = null;
System.out.println("请求授权的账号为:"+username);
password = accountService.getPasswordByName(username);
if(password == null){
throw new RuntimeException("账号不存在,授权失败!");
}
System.out.println("查询到的密码为:"+password);
return new User(username, password, AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER"));
}
}
五、其中用到的查询数据库的类
5.1、实体类
package com.yonyou.entity;
import lombok.Data;
import javax.persistence.*;
@Entity
@Table(name = "account")
@Data
public class Account {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(columnDefinition = "varchar(20) NOT NULL comment '用户名'")
private String username;
@Column(columnDefinition = "varchar(100) NOT NULL comment '密码'")
private String password;
}
5.2、AccountRepository 类
public interface AccountRepository extends JpaRepository<Account, Integer> {
@Query(nativeQuery = true, value = "select password from account where username=?1")
String getPasswordByName(String username);
}
5.3、AccountServiceImpl 类
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountRepository accountRepository;
@Override
public String getPasswordByName(String username) {
return accountRepository.getPasswordByName(username);
}
}
六、测试类 HelloController
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(){
return "HelloWorld";
}
}
七、测试结果
1、获取授权token
2、测试
八、注意
- 表里的
用户密码
要采用 oauth2
独有的加密方式
先进行加密,再进行保存,否则无效。
@RunWith(SpringRunner.class)
@SpringBootTest
public class Oauth2ApplicationTests {
@Autowired
private AccountRepository accountRepository;
@Autowired
private PasswordEncoder passwordEncoder;
@Test
public void contextLoads() {
Account account = new Account();
account.setUsername("admin");
String password = "123456";
password = passwordEncoder.encode(password);
account.setPassword(password);
accountRepository.save(account);
}
}