SpringBoot中如何使用Oauth2完成密码策略授权?
2019-09-10 07:09
2266 查看
Oauth2如何使用密码策略完成授权?
一、导入相关依赖
- POM文件
<!-- 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 配置 jpa: show-sql: true hibernate: ddl-auto: update database-platform: org.hibernate.dialect.MySQL5InnoDBDialect #不加这句则默认为myisam引擎 database: mysql #security: # oauth2: # resource: # ####从认证授权中心上验证token # tokenInfoUri: http://localhost:8092/oauth/check_token # preferTokenInfo: true # client: ## 获取accesstoken地址 # accessTokenUri: http://localhost:8092/oauth/token # userAuthorizationUri: http://localhost:8092/oauth/authorize #授权地址 # clientId: client # clientSecret: client
二、项目结构
三、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); } /** * 客户端配置(给谁发令牌) * @param clients * @throws Exception */ @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory().withClient("client") .secret(passwordEncoder.encode("client")) //有效时间 2小时 .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 (资源服务器)
/** * 资源服务配置 * * @ EnableResourceServer 启用资源服务 * @ EnableWebSecurity 启用web安全 * @ EnableGlobalMethodSecurity 启用全局方法安全注解,就可以在方法上使用注解来对请求进行过滤 */ @Configuration @EnableResourceServer//开启资源服务 public class ResourceServerConfigurer extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { // 对 api/order 请求进行拦截 验证 accessToken 与controller 的要有关系 http.authorizeRequests() //放行的路径 .antMatchers(Constant.IGNORE_PATHS .toArray(new String[Constant.IGNORE_PATHS.size()]) ).permitAll() .anyRequest().authenticated() .and() .httpBasic().and().csrf().disable();//关闭打开的csrf保护 跨域有问题 } }
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; /** * 安全配置 * * @ EnableWebSecurity 启用web安全配置 * @ EnableGlobalMethodSecurity 启用全局方法安全注解,就可以在方法上使用注解来对请求进行过滤 */ @Configuration @EnableWebSecurity//开启WebSecurity功能 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<>(); //swagger2的访问路径及资源 IGNORE_PATHS.add("/v2/api-docs"); IGNORE_PATHS.add("/swagger-ui.html"); IGNORE_PATHS.add("/webjars/**"); } }
四、密码策略的验证
DomainUserDetailsService 类
/** * 用户信息服务 * 实现 Spring Security的UserDetailsService接口方法,用于身份认证 */ @Service public class DomainUserDetailsService implements UserDetailsService { @Autowired //这里的AccountService是service层中从数据库查找对应的数据类 private AccountService accountService; /** * 根据用户名查找账户信息并返回用户信息实体 * @param username 用户名 * @return 用于身份认证的 UserDetails 用户信息实体 * @throws UsernameNotFoundException */ @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> { /** * 根据用户名查询密码 * @param username * @return */ @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"; //先使用 passwordEncoder 进行加密 password = passwordEncoder.encode(password); //设值进去 account.setPassword(password); //保存 accountRepository.save(account); } }
相关文章推荐
- Spring-Boot中如何使用多线程处理任务
- 如何使用eclipse搭建SpringBoot项目
- 如何在Spring Boot中使用TDD写出高质量的接口
- spring-boot+mybatis开发实战:如何在spring-boot中使用myabtis持久层框架
- SpringBoot学习-如何使用mybatis-generator-maven-plugin自动生成代码
- springboot学习:spring-boot中如何使用thymeleaf模板引擎
- spring boot(六):如何优雅的使用mybatis
- spring整合rmi 如何使用安全策略
- SpringBoot入门学习一(如何使用IDEA创建一个SpringBoot应用)
- spring boot(六)如何优雅的使用mybatis
- springboot学习(2)springboot使用JdbcTemplate完成对数据库的增删改查
- SpringBoot笔记3---如何读写数据库之使用CrudRepository中提供的方法来读写数据库
- spring boot项目中如何使用日志
- springboot使用JPA时间类型如何模糊查询
- 转载:Spring Boot (六):如何优雅的使用mybatis
- (3)spring boot如何使用第三方json解析框架
- 详解Spring-Boot中如何使用多线程处理任务
- 如何使用Spring Boot快速创建Web应用
- 80. Hibernate 5.0命名策略使用naming-strategy 不起作用【从零开始学Spring Boot】
- 如何使用MongoDB+Springboot实现分布式ID?