开源框架-SpringCloud系列

springcloud-sso单点登陆(二)

2019-12-24  本文已影响0人  凌康ACG

单点登陆的实现方式有多种:
1、基于cas来做
2、spring cloud oauth2的spring全家桶
3、自定义jwt(不推荐)
下面我们基于spring全家桶来做一个单点登陆系统2019年12月23日最新springboot版本2.2.2.RELEASE;由于篇幅问题,我们分成两篇文章。
基于上一篇https://www.jianshu.com/p/80b125ea8e76
源码:https://github.com/xcocean/spring-cloud-sso

一、创建用户客户端

创建一个在根目录下创建business-user文件夹,在business-user下创建pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.qbccn</groupId>
        <artifactId>parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <groupId>com.qbccn</groupId>
    <artifactId>business-user</artifactId>
    <description>用户中心</description>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- oauth2 server  start-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>
        <!-- oauth2 server  end-->

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
            <exclusions>
                <!-- 排除 tomcat-jdbc 以使用 HikariCP -->
                <exclusion>
                    <groupId>org.apache.tomcat</groupId>
                    <artifactId>tomcat-jdbc</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.qbccn.UseApplication</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

关键配置如下:

package com.qbccn.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;

@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class UserResourceConfiguration extends ResourceServerConfigurerAdapter {

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .exceptionHandling()
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                //需要授权的路径
                .antMatchers("/user/**").hasAnyRole("USER")
                .antMatchers("/admin/**").hasAnyRole("ADMIN")
                .anyRequest().permitAll(); //其他页面所有人能访问
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        // 配置资源 ID --对应sso的资源id
        resources.resourceId("backend-resources");
    }
}

application.yml,由于sso服务使用了8080端口,这里改成8081端口

server:
  port:8081
spring:
  main:
    allow-bean-definition-overriding: true
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/sso?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8
    username: root
    password: 123456
    hikari:
      minimum-idle: 1
      idle-timeout: 600000
      maximum-pool-size: 10
      auto-commit: true
      pool-name: MyHikariCP
      max-lifetime: 1800000
      connection-timeout: 30000
      connection-test-query: SELECT 1

security:
  oauth2:
    client:
      client-id: client
      client-secret: secret
      access-token-uri: http://localhost:8080/oauth/token
      user-authorization-uri: http://localhost:8080/oauth/authorize
    resource:
      token-info-uri: http://localhost:8080/oauth/check_token
mybatis:
  mapper-locations: classpath:mapper/*.xml

项目截图如下:


image.png

二、测试

启动项目后:浏览器访问http://localhost:8081/user/info/lk

image.png
我们用postman登陆拿到token:
image.png
带上token访问:http://localhost:8081/user/info/lk?access_token=fd3a7ca5-af58-48e7-8351-bc3272109189
image.png
lk这个用户没有admin权限,我们访问admin看看
image.png
可以看到我们被拒绝访问。用postman登陆admin获取token再访问:
image.png
http://localhost:8081/admin/userList?access_token=d5e43187-026e-4bb7-8af7-dade7b657f47
image.png
我们停止认证服务器再请求会报错,其中引入okhttp是打算从business-user做登陆的。
关于如何在oauth2 client拿到sso的用户登录信息,比如权限、角色、账号呀?在客户端直接调用即可,他会根据你请求的token去sso获取相关信息,我们不需要输入账号:
//拿用户名,类似普通项目的session get(username)
SecurityContextHolder.getContext().getAuthentication().getName();

前后端分离就是基于此完成,实际的场景并没有这么简单,有很多开发规范需要遵守。但是核心验证仍是这样,喜欢就点个赞吧_

上一篇下一篇

猜你喜欢

热点阅读