SpringOauth2简单登陆

SpringOauth2实现Jdbc简单认证登陆

创建一个SpringBoot工程
依赖如下:

<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.10.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		
		<dependency>
			<groupId>org.springframework.security.oauth</groupId>
			<artifactId>spring-security-oauth2</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>
			<version>8.0.16</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

这里主要依赖的是Spring Security 、Spring Security Oauth2 依赖,创建好项目后我们创建一个User类并且实现UserDetail接口如下:

public class UserInfo implements UserDetails{

    private String name;

    private String email;

    private String password;

    public void setPassword(String password) {
        this.password = password;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Transient
    private List<GrantedAuthority> authorityList;

    public List<GrantedAuthority> getAuthorityList() {
        return authorityList;
    }

    public void setAuthorityList(List<GrantedAuthority> authorityList) {
        this.authorityList = authorityList;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorityList;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return name;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

    @Override
    public String toString() {
        return "UserInfo{" +
                "name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", password='" + password + '\'' +
                ", authorityList=" + authorityList +
                '}';
    }
}

这里UserDetail接口我就不多解释了,这几个方法大家都应该很清楚,然后我们创建一个CustomerUserService去实现UserDetailsService接口的loadUserByUsername方法:

@Service
public class CustomerUserService implements UserDetailsService {
    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        UserInfo user = new UserInfo();
        user.setName(username);
        user.setPassword("123456");

        log.info("username ->" + username);

        if (user.getName().equals("zhoubiao")) {
            List<GrantedAuthority> auths = new ArrayList<>();
            auths.add(new SimpleGrantedAuthority("ROLE_USER"));
            user.setAuthorityList(auths);
            log.info("user ->" + user);
            return user;
        }

        return null;
    }
}

这里的代码很简单。这里的角色权限都是写死的。不管是用mybatis的mapper还是spring data jpa 都可以通过注入到这里来进行查询操作。这里为了简化操作。我就写死了。

然后我们创建我们的授权服务器:

@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServer extends
        AuthorizationServerConfigurerAdapter {

    @Resource
    private DataSource dataSource;

    @Bean
    public ClientDetailsService clientDetailsService() {
        return new JdbcClientDetailsService(dataSource);
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients)
            throws Exception {
        clients.jdbc(dataSource);
    }

注意这里的DataSource是依赖Spring Data Jpa 中为我们封装的Spring Jdbc的相关配置依赖。

下面就是我们的资源服务器配置了如下:

@Configuration
@EnableResourceServer
public class OAuth2ResourceServer extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .anyRequest()
            .authenticated()
        .and()
            .requestMatchers()
            .antMatchers("/api/**");
    }
    
}

这里注意资源服务器应该是和授权服务器分开的,这里为了演示方便,我把他们放在一起了。这里对/api/下的所有请求进行拦截认证。

我们在pom.xml中引入了Security 的依赖,那么我们是需要使用到它的,那么我们创建一个WebSecurityConfig并且继承自WebSecurityConfigurerAdapter这个适配器类

@EnableWebSecurity
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private CustomerUserService customerUserService;
    @Autowired
    public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder

       .userDetailsService(this.customerUserService);
    }
}

这里使用了AuthenticationManagerBuilder来管理认证信息,最后我们创建一个UserController 来进行测试:

@Controller
public class UserController {

    @RequestMapping("/api/userinfo")
    public ResponseEntity<UserInfo> getUserInfo() {
        UserInfo user = (UserInfo) SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        String email = user.getUsername();
        user.setName(user.getUsername());
        user.setEmail(email);

        return ResponseEntity.ok(user);
    }
}

下面是application.properties配置:

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/_oauth2
spring.datasource.username=root
spring.datasource.password=root

#jpa
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

下面是这个资源需要的sql,这里为什么需要创建sql呢,因为我们是走的jdbc模式,下面这个sql的结构可以从JdbcClientDetailsService 这个类从获取,如下:
在这里插入图片描述

SET NAMES utf8;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
--  Table structure for `oauth_client_details`
-- ----------------------------
DROP TABLE IF EXISTS `oauth_client_details`;
CREATE TABLE `oauth_client_details` (
  `client_id` varchar(48) NOT NULL,
  `resource_ids` varchar(256) DEFAULT NULL,
  `client_secret` varchar(256) DEFAULT NULL,
  `scope` varchar(256) DEFAULT NULL,
  `authorized_grant_types` varchar(256) DEFAULT NULL,
  `web_server_redirect_uri` varchar(256) DEFAULT NULL,
  `authorities` varchar(256) DEFAULT NULL,
  `access_token_validity` int(11) DEFAULT NULL,
  `refresh_token_validity` int(11) DEFAULT NULL,
  `additional_information` varchar(4096) DEFAULT NULL,
  `autoapprove` varchar(256) DEFAULT NULL,
  PRIMARY KEY (`client_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `oauth_client_details`
-- ----------------------------
BEGIN;
INSERT INTO `oauth_client_details` VALUES ('clientapp', null, '112233', 'read_userinfo', 'authorization_code', 'http://localhost:9001/callback', null, '3600', null, null, null);
COMMIT;

SET FOREIGN_KEY_CHECKS = 1;

然后我们使用chrome浏览器访问http://localhost:8080/oauth/authorize?client_id=clientapp&redirect_uri=http://localhost:9001/callback&response_type=code&scope=read_userinfo

然后出现了身份认证:
在这里插入图片描述
我们输入账号和密码点击登陆后:

在这里插入图片描述
这里提示我们授权。我们点击Approve,如果点击了Deny就是拒绝授权。

在这里插入图片描述
这里我们就拿到了授权码,然后我们使用postman之类的http来进行后面的测试:
在这里插入图片描述
在这里插入图片描述
这里我们要填入客户端id 和密码,这里是来自数据里面的。这里所有的表单填入的信息都来自数据库表中的数据。

然后我们点击发送:
在这里插入图片描述
这里就可以拿到token了。然后我们就可以用token 来换取我们的api服务了
在这里插入图片描述

在这里插入图片描述
这里就拿到了我们api提供的信息了。

总结

这里使用了授权码模式的oauth2的认证,总体来说很简单的。注意这里的实验是不能用在生产级别的,如果要用到生产级,那么还需要对代码进行多次的封装和配置。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值