美文网首页
Oauth2.0 实现SSO单点登陆

Oauth2.0 实现SSO单点登陆

作者: 久伴我还是酒伴我 | 来源:发表于2019-04-10 16:52 被阅读0次

    简介

    首先声明本文章是在不要乱摸基础上进行部分修改,思路和核心代码未做调整,写本片文章主要是为了加深自己的单点登陆的印象,巩固自己小小的知识面,所以将实现的过程记录下来。话不多说,一个字:

    服务架构

    image.png

    \color{red}{本项目分为三个服务}

    authentication-center 授权服务
    oauth2-sso-client-member 用户管理服务
    oauth2-sso-client-order 订单服务

    数据库

    /*
    
    SET NAMES utf8mb4;
    
    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(256) CHARACTER SET utf8 NOT NULL,
    
      `resource_ids` varchar(256) CHARACTER SET utf8 DEFAULT NULL,
    
      `client_secret` varchar(256) CHARACTER SET utf8 DEFAULT NULL,
    
      `scope` varchar(256) CHARACTER SET utf8 DEFAULT NULL,
    
      `authorized_grant_types` varchar(256) CHARACTER SET utf8 DEFAULT NULL,
    
      `web_server_redirect_uri` varchar(256) CHARACTER SET utf8 DEFAULT NULL,
    
      `authorities` varchar(256) CHARACTER SET utf8 DEFAULT NULL,
    
      `access_token_validity` int(11) DEFAULT NULL,
    
      `refresh_token_validity` int(11) DEFAULT NULL,
    
      `additional_information` varchar(4096) CHARACTER SET utf8 DEFAULT NULL,
    
      `autoapprove` varchar(256) CHARACTER SET utf8 DEFAULT NULL,
    
      PRIMARY KEY (`client_id`)
    
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    
    
    
    -- ----------------------------
    
    -- Records of oauth_client_details
    
    -- ----------------------------
    
    BEGIN;
    
    INSERT INTO `oauth_client_details` VALUES ('OrderManagement', NULL, '$2a$10$8yVwRGY6zB8wv5o0kRgD0ep/HVcvtSZUZsYu/586Egxc1hv3cI9Q6', 'all', 'authorization_code,refresh_token', 'http://localhost:8083/orderSystem/login', NULL, 7200, NULL, NULL, 'true');
    
    INSERT INTO `oauth_client_details` VALUES ('UserManagement', NULL, '$2a$10$ZRmPFVgE6o2aoaK6hv49pOt5BZIKBDLywCaFkuAs6zYmRkpKHgyuO', 'all', 'authorization_code,refresh_token', 'http://localhost:8082/memberSystem/login', NULL, 7200, NULL, NULL, 'true');
    
    COMMIT;
    
    
    
    -- ----------------------------
    
    -- Table structure for sys_permission
    
    -- ----------------------------
    
    DROP TABLE IF EXISTS `sys_permission`;
    
    CREATE TABLE `sys_permission` (
    
      `id` int(11) NOT NULL AUTO_INCREMENT,
    
      `pid` int(11) DEFAULT '0' COMMENT '父ID',
    
      `type` tinyint(4) NOT NULL COMMENT '资源类型(1:菜单,2:按钮,3:操作)',
    
      `name` varchar(64) CHARACTER SET latin1 NOT NULL COMMENT '资源名称',
    
      `code` varchar(64) CHARACTER SET latin1 NOT NULL COMMENT '资源标识(或者叫权限字符串)',
    
      `uri` varchar(64) CHARACTER SET latin1 DEFAULT NULL COMMENT '资源URI',
    
      `seq` int(11) DEFAULT '1' COMMENT '序号',
    
      `create_user` varchar(64) CHARACTER SET latin1 DEFAULT NULL,
    
      `create_time` datetime DEFAULT NULL,
    
      `update_user` varchar(64) CHARACTER SET latin1 DEFAULT NULL,
    
      `update_time` datetime DEFAULT NULL,
    
      PRIMARY KEY (`id`),
    
      UNIQUE KEY `code` (`code`),
    
      KEY `idx_type` (`type`) USING BTREE
    
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
    
    
    
    -- ----------------------------
    
    -- Records of sys_permission
    
    -- ----------------------------
    
    BEGIN;
    
    INSERT INTO `sys_permission` VALUES (1, 0, 3, 'add', 'member:add', '/member/add', 1, 'system', '2019-03-03 18:50:17', 'system', '2019-03-03 18:50:20');
    
    COMMIT;
    
    
    -- ----------------------------
    
    -- Table structure for sys_role
    
    -- ----------------------------
    
    DROP TABLE IF EXISTS `sys_role`;
    
    CREATE TABLE `sys_role` (
    
      `id` int(11) NOT NULL AUTO_INCREMENT,
    
      `role_name` varchar(32) NOT NULL COMMENT '角色名称',
    
      `role_code` varchar(32) NOT NULL,
    
      `role_description` varchar(64) DEFAULT NULL COMMENT '角色描述',
    
      `create_user` varchar(64) DEFAULT NULL,
    
      `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
    
      `update_user` varchar(64) DEFAULT NULL,
    
      `update_time` datetime DEFAULT NULL,
    
      PRIMARY KEY (`id`)
    
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;
    
    
    
    -- ----------------------------
    
    -- Records of sys_role
    
    -- ----------------------------
    
    BEGIN;
    
    INSERT INTO `sys_role` VALUES (1, '员工', 'normal', '普通员工', 'system', '2019-02-12 11:14:41', NULL, NULL);
    
    INSERT INTO `sys_role` VALUES (2, '部门经理', 'manager', '部门经理', 'system', '2019-02-12 11:15:37', NULL, NULL);
    
    INSERT INTO `sys_role` VALUES (3, '客服', 'kefu', '客服', 'system', '2019-02-12 11:16:27', NULL, NULL);
    
    COMMIT;
    
    
    
    -- ----------------------------
    
    -- Table structure for sys_role_permission
    
    -- ----------------------------
    
    DROP TABLE IF EXISTS `sys_role_permission`;
    
    CREATE TABLE `sys_role_permission` (
    
      `id` int(11) NOT NULL AUTO_INCREMENT,
    
      `role_id` int(11) NOT NULL COMMENT '角色ID',
    
      `permission_id` int(11) NOT NULL COMMENT '权限ID',
    
      PRIMARY KEY (`id`)
    
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
    
    
    
    -- ----------------------------
    
    -- Records of sys_role_permission
    
    -- ----------------------------
    
    BEGIN;
    
    INSERT INTO `sys_role_permission` VALUES (1, 2, 1);
    
    COMMIT;
    
    
    
    -- ----------------------------
    
    -- Table structure for sys_user
    
    -- ----------------------------
    
    DROP TABLE IF EXISTS `sys_user`;
    
    CREATE TABLE `sys_user` (
    
      `id` int(11) NOT NULL AUTO_INCREMENT,
    
      `username` varchar(64) NOT NULL COMMENT '账号',
    
      `password` varchar(256) NOT NULL COMMENT '密码',
    
      `nickname` varchar(64) NOT NULL COMMENT '昵称',
    
      `email` varchar(64) DEFAULT NULL COMMENT '邮箱',
    
      `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(0:锁定,1:解锁)',
    
      `create_user` varchar(64) DEFAULT NULL,
    
      `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
    
      `update_user` varchar(64) DEFAULT NULL,
    
      `update_time` datetime DEFAULT NULL,
    
      PRIMARY KEY (`id`)
    
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;
    
    
    
    -- ----------------------------
    
    -- Records of sys_user
    
    -- ----------------------------
    
    BEGIN;
    
    INSERT INTO `sys_user` VALUES (1, 'admin', 'admin', '管理员', 'abc@123.com', 1, 'system', '2019-02-12 11:12:19', NULL, NULL);
    
    INSERT INTO `sys_user` VALUES (2, 'zhangsan', '123456', '张三', 'zhangsan@126.com', 1, 'system', '2019-02-12 11:13:27', NULL, NULL);
    
    COMMIT;
    
    
    
    -- ----------------------------
    
    -- Table structure for sys_user_role
    
    -- ----------------------------
    
    DROP TABLE IF EXISTS `sys_user_role`;
    
    CREATE TABLE `sys_user_role` (
    
      `id` int(11) NOT NULL AUTO_INCREMENT,
    
      `user_id` int(11) NOT NULL COMMENT '用户ID',
    
      `role_id` int(11) NOT NULL COMMENT '角色ID',
    
      PRIMARY KEY (`id`)
    
    ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4;
    
    
    
    -- ----------------------------
    
    -- Records of sys_user_role
    
    -- ----------------------------
    
    BEGIN;
    
    INSERT INTO `sys_user_role` VALUES (1, 1, 1);
    
    INSERT INTO `sys_user_role` VALUES (2, 1, 2);
    
    INSERT INTO `sys_user_role` VALUES (3, 1, 3);
    
    INSERT INTO `sys_user_role` VALUES (4, 2, 2);
    
    COMMIT;
    
    
    
    SET FOREIGN_KEY_CHECKS = 1;
    

    授权服务

    1. 代码目录

    image.png

    2. Maven 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.3.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.glj</groupId>
        <artifactId>authentication-center</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>authentication-center</name>
        <description>授权中心</description>
    
        <properties>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.security.oauth.boot</groupId>
                <artifactId>spring-security-oauth2-autoconfigure</artifactId>
                <version>2.1.3.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
            <dependency>
                <groupId>org.thymeleaf.extras</groupId>
                <artifactId>thymeleaf-extras-springsecurity4</artifactId>
                <version>3.0.2.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.session</groupId>
                <artifactId>spring-session-data-redis</artifactId>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
            </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>
            </dependency>
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <version>3.8.1</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.56</version>
            </dependency>
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>3.0.6</version>
            </dependency>
            <!-- 与swagger一起使用,需要注意-->
            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger2</artifactId>
                <version>2.8.0</version>
                <exclusions>
                    <exclusion>
                        <artifactId>org.mapstruct</artifactId>
                        <groupId>mapstruct</groupId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger-ui</artifactId>
                <version>2.8.0</version>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    

    3. application.yml

    spring:
      datasource:
        url: jdbc:mysql://127.0.0.1:3306/security_oauth?serverTimezone=GMT%2B8&characterEncoding=utf8&useSSL=false
        password: test
        username: test
        driver-class-name: com.mysql.cj.jdbc.Driver
      session:
        store-type: redis
      redis:
        host: 127.0.0.1
        port: 6379
    server:
      port: 8080
    

    4. AuthorizationServerConfig 内容

    package com.glj.config;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
    import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
    import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
    import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
    import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
    import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
    import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
    
    import javax.sql.DataSource;
    
    /**
     * @ClassName AuthorizationServerConfig
     * @Description TODO
     * @Author gaoleijie
     * @Date 2019/4/3 19:28
     **/
    @EnableAuthorizationServer
    @Configuration
    public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
        @Autowired
        private DataSource dataSource;
    
        @Override
        public void configure(AuthorizationServerSecurityConfigurer security) {
            security.allowFormAuthenticationForClients();
            security.tokenKeyAccess("isAuthenticated()");
        }
    
        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.jdbc(dataSource);
        }
    
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
            endpoints.accessTokenConverter(jwtAccessTokenConverter());
            endpoints.tokenStore(jwtTokenStore());
    //        endpoints.tokenServices(defaultTokenServices());
        }
    
        @Bean
        public JwtTokenStore jwtTokenStore() {
            return new JwtTokenStore(jwtAccessTokenConverter());
        }
    
        @Bean
        public JwtAccessTokenConverter jwtAccessTokenConverter() {
            JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
            jwtAccessTokenConverter.setSigningKey("cjs");   //  Sets the JWT signing key
            return jwtAccessTokenConverter;
        }
    }
    
    

    5. MyUserDetailsService 内容

    package com.glj.config;
    
    import com.alibaba.fastjson.JSON;
    import com.glj.entity.SysRolePo;
    import com.glj.entity.SysUserPo;
    import com.glj.service.ISysUserService;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.core.authority.SimpleGrantedAuthority;
    import org.springframework.security.core.userdetails.User;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.security.crypto.password.PasswordEncoder;
    import org.springframework.stereotype.Service;
    import org.springframework.util.StringUtils;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @ClassName MyUserDetailsService
     * @Description TODO
     * @Author gaoleijie
     * @Date 2019/4/4 14:32
     **/
    @Service
    @Slf4j
    public class MyUserDetailsService implements UserDetailsService {
        @Autowired
        private ISysUserService userService;
        @Autowired
        private PasswordEncoder passwordEncoder;
    
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            SysUserPo sysUserPo = userService.getUserByUserCode(username);
            if (StringUtils.isEmpty(sysUserPo)) {
                log.warn("用户{}不存在", username);
                throw new UsernameNotFoundException("【" + username + "】用户不存在!");
            }
            log.info(passwordEncoder.encode(sysUserPo.getPassword()) + "原" + sysUserPo.getPassword());
            List<SimpleGrantedAuthority> authorities = new ArrayList<>();
            for (SysRolePo role : sysUserPo.getRolePoList()) {
                role.getPermissionPoList().stream().forEach(d -> {
                    authorities.add(new SimpleGrantedAuthority(d.getCode()));
                });
            }
            log.info("登录成功!用户: {}", JSON.toJSONString(sysUserPo));
            return new User(sysUserPo.getUsername(), passwordEncoder.encode(sysUserPo.getPassword()), authorities);
        }
    }
    

    6. WebSecurityConfig 内容

    package com.glj.config;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    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.builders.WebSecurity;
    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;
    
    /**
     * @ClassName WebSecurityConfig
     * @Description TODO
     * @Author gaoleijie
     * @Date 2019/4/3 19:30
     **/
    @Configuration
    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        @Autowired
        private MyUserDetailsService userDetailsService;
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
        }
    
        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().antMatchers("/assets/**", "/css/**", "/images/**");
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.formLogin()
                    .loginPage("/login")
                    .failureUrl("/login?error=true")
                    .and()
                    .authorizeRequests()
                    .antMatchers("/login").permitAll()
                    .anyRequest()
                    .authenticated()
                    .and().csrf().disable().cors();
        }
    
        @Bean
        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
    }
    

    8. LoginController 内容

    package com.glj.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    
    /**
     * @ClassName LoginController
     * @Description TODO
     * @Author gaoleijie
     * @Date 2019/4/3 19:31
     **/
    @Controller
    public class LoginController {
        @GetMapping("/login")
        public String login() {
            return "login";
        }
    
        @GetMapping("/")
        public String index() {
            return "index";
        }
    }
    

    9. 阐述

    Service Mapper 和Entity 我用的是Mybatis Plus 直接根据表生成即可,由于文件太多,就不粘贴了,需要注意的是Mybaits plus 生成的实体对象中需要自己添加对应的List集合(如:该用户有那些角色,需要添加角色List),无需映射,需要添加 @TableField(exist = false)进行忽略,否则会出错。

    10. resource 目录

    image.png

    11. index.html 内容

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <!-- Required meta tags -->
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
      <title>Purple Admin</title>
    
      <link rel="stylesheet" href="css/style.css">
    </head>
    <body>
    <div class="container-scroller">
      <!-- partial -->
      <div class="container-fluid page-body-wrapper">
        <div class="main-panel">
          <div class="content-wrapper">
            <div class="page-header">
              <h3 class="page-title">
                  <span class="page-title-icon bg-gradient-primary text-white mr-2">
                    <i class="mdi mdi-home"></i>                 
                  </span>
                欢迎来到王者荣耀
              </h3>
            </div>
            <div class="row">
              <div class="col-md-4 stretch-card grid-margin">
                <div class="card bg-gradient-danger card-img-holder text-white">
                  <div class="card-body">
                    <img src="images/dashboard/circle.svg" class="card-img-absolute" alt="circle-image"/>
                    <h2 class="mb-5"><a href="http://127.0.0.1:8082/memberSystem/member/list" style="color: white">用户管理</a>
                    </h2>
                  </div>
                </div>
              </div>
              <div class="col-md-4 stretch-card grid-margin">
                <div class="card bg-gradient-info card-img-holder text-white">
                  <div class="card-body">
                    <img src="images/dashboard/circle.svg" class="card-img-absolute" alt="circle-image"/>
                    <h2 class="mb-5"><a href="http://127.0.0.1:8083/orderSystem/order/list" style="color: white">订单管理</a>
                    </h2>
                  </div>
                </div>
              </div>
              <div class="col-md-4 stretch-card grid-margin">
                <div class="card bg-gradient-success card-img-holder text-white">
                  <div class="card-body">
                    <img src="images/dashboard/circle.svg" class="card-img-absolute" alt="circle-image"/>
                    <h2 class="mb-5">营销管理</h2>
                  </div>
                </div>
              </div>
            </div>
    
            <div class="row">
              <div class="col-md-4 stretch-card grid-margin">
                <div class="card bg-gradient-danger card-img-holder text-white">
                  <div class="card-body">
                    <img src="images/dashboard/circle.svg" class="card-img-absolute" alt="circle-image"/>
                    <h2 class="mb-5">运营管理</h2>
                  </div>
                </div>
              </div>
              <div class="col-md-4 stretch-card grid-margin">
                <div class="card bg-gradient-info card-img-holder text-white">
                  <div class="card-body">
                    <img src="images/dashboard/circle.svg" class="card-img-absolute" alt="circle-image"/>
                    <h2 class="mb-5">商户管理</h2>
                  </div>
                </div>
              </div>
              <div class="col-md-4 stretch-card grid-margin">
                <div class="card bg-gradient-success card-img-holder text-white">
                  <div class="card-body">
                    <img src="images/dashboard/circle.svg" class="card-img-absolute" alt="circle-image"/>
                    <h2 class="mb-5">财务管理</h2>
                  </div>
                </div>
              </div>
            </div>
          </div>
          <!-- content-wrapper ends -->
          <!-- partial -->
        </div>
        <!-- main-panel ends -->
      </div>
      <!-- page-body-wrapper ends -->
    </div>
    <!-- container-scroller -->
    
    
    </body>
    
    </html>
    

    12. login.html 内容

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>Ela Admin - HTML5 Admin Template</title>
        <meta name="description" content="Ela Admin - HTML5 Admin Template">
        <meta name="viewport" content="width=device-width, initial-scale=1">
    
        <link type="text/css" rel="stylesheet" th:href="@{/assets/css/normalize.css}">
        <link type="text/css" rel="stylesheet" th:href="@{/assets/bootstrap-4.3.1-dist/css/bootstrap.min.css}">
        <link type="text/css" rel="stylesheet" th:href="@{/assets/css/font-awesome.min.css}">
        <link type="text/css" rel="stylesheet" th:href="@{/assets/css/style.css}">
    
    </head>
    <body class="bg-dark">
    
    <div class="sufee-login d-flex align-content-center flex-wrap">
        <div class="container">
            <div class="login-content">
                <div class="login-logo">
                    <h1 style="color: #57bf95;">欢迎来到王者荣耀</h1>
                </div>
                <div class="login-form">
                    <form th:action="@{/login}" method="post">
                        <div class="form-group">
                            <label>Username</label>
                            <input type="text" class="form-control" name="username" placeholder="Username">
                        </div>
                        <div class="form-group">
                            <label>Password</label>
                            <input type="password" class="form-control" name="password" placeholder="Password">
                        </div>
                        <div class="checkbox">
                            <label>
                                <input type="checkbox"> Remember Me
                            </label>
                            <label class="pull-right">
                                <a href="#">Forgotten Password?</a>
                            </label>
                        </div>
                        <span th:if="${param.error}"
                              th:text="${session.SPRING_SECURITY_LAST_EXCEPTION.message}=='Bad credentials'?'账号/密码错误!':${ession.SPRING_SECURITY_LAST_EXCEPTION.message}"
                              class="bg-danger"/>
                        <button type="submit" class="btn btn-success btn-flat m-b-30 m-t-30" style="font-size: 18px;">登录
                        </button>
                    </form>
                </div>
            </div>
        </div>
    </div>
    
    
    <script type="text/javascript" th:src="@{/assets/js/jquery-2.1.4.min.js}"></script>
    <script type="text/javascript" th:src="@{/assets/bootstrap-4.3.1-dist/js/bootstrap.min.js}"></script>
    <script type="text/javascript" th:src="@{/assets/js/main.js}"></script>
    
    </body>
    </html>
    

    到此授权服务器就集成完毕了。

    用户管理服务

    代码目录

    image.png

    1. Maven 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.4.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.glj</groupId>
        <artifactId>oauth2-sso-client-member</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>oauth2-sso-client-member</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-oauth2-client</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.security.oauth.boot</groupId>
                <artifactId>spring-security-oauth2-autoconfigure</artifactId>
                <version>2.1.3.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.thymeleaf.extras</groupId>
                <artifactId>thymeleaf-extras-springsecurity5</artifactId>
                <version>3.0.4.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </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>
            </dependency>
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    

    2. application.yml 内容

    server:
      port: 8082
      servlet:
        context-path: /memberSystem
    security:
      oauth2:
        client:
          client-id: UserManagement
          client-secret: user123
          access-token-uri: http://127.0.0.1:8080/oauth/token
          user-authorization-uri: http://127.0.0.1:8080/oauth/authorize
        resource:
          jwt:
            key-uri: http://127.0.0.1:8080/oauth/token_key
    

    3. WebSecurityConfig 内容

    package com.glj.member.config;
    
    import com.glj.member.util.EnvironmentUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.builders.WebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    
    
    /**
     * @author gaoleijie
     * @date 2019-03-03
     */
    @EnableOAuth2Sso
    @Configuration
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private EnvironmentUtils environmentUtils;
    
        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().antMatchers("/bootstrap/**");
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            if ("local".equals(environmentUtils.getActiveProfile())) {
                http.authorizeRequests().anyRequest().permitAll();
            } else {
                http.logout().logoutSuccessUrl("http://127.0.0.1:8080/logout")
                        .and()
                        .authorizeRequests()
                        .anyRequest().authenticated()
                        .and()
                        .csrf().disable();
            }
        }
    }
    
    

    4. MemberController 内容

    package com.glj.member.controller;
    
    import org.springframework.security.access.prepost.PreAuthorize;
    import org.springframework.security.core.Authentication;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import java.security.Principal;
    
    /**
     * @author gaoleijie
     * @date 2019-03-03
     */
    @Controller
    @RequestMapping("/member")
    public class MemberController {
    
        @GetMapping("/list")
        public String list() {
            return "member/list";
        }
    
        @GetMapping("/info")
        @ResponseBody
        public Principal info(Principal principal) {
            return principal;
        }
    
        @GetMapping("/me")
        @ResponseBody
        public Authentication me(Authentication authentication) {
            return authentication;
        }
    
        @PreAuthorize("hasAuthority('member:save')")
        @ResponseBody
        @PostMapping("/add")
        public String add() {
            return "add";
        }
    
        @PreAuthorize("hasAuthority('member:detail')")
        @ResponseBody
        @GetMapping("/detail")
        public String detail() {
            return "detail";
        }
    }
    

    5. Oauth2SsoClientMemberApplication 内容

    package com.glj.member;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.Bean;
    import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
    import org.springframework.security.oauth2.client.OAuth2ClientContext;
    import org.springframework.security.oauth2.client.OAuth2RestTemplate;
    import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
    
    @SpringBootApplication
    @EnableGlobalMethodSecurity(prePostEnabled =true)
    public class Oauth2SsoClientMemberApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(Oauth2SsoClientMemberApplication.class, args);
        }
    
        @Bean
        public OAuth2RestTemplate oauth2RestTemplate(OAuth2ClientContext oauth2ClientContext,OAuth2ProtectedResourceDetails details) {
            return new OAuth2RestTemplate(details, oauth2ClientContext);
        }
    
    }
    

    6. resource 目录

    image.png

    7. list.html 内容

    <!DOCTYPE html>
    <html lang="zh" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>会员列表</title>
    
        <link type="text/css" rel="stylesheet" th:href="@{/static/bootstrap/css/bootstrap.min.css}">
    
    </head>
    <body>
    <h3>当前登录用户:<span th:text="${#authentication.name}"></span> | <a th:href="@{/logout}">退出</a></h3>
    <h2>这是会员管理列表页面</h2>
    <table class="table">
        <tr>
            <th>名称</th>
            <th>职业</th>
            <th>简介</th>
            <th>创建时间</th>
            <th>操作</th>
        </tr>
        <tr>
            <td style="font-size: 20px;">蓝忘机</td>
            <td>驱邪师</td>
            <td>蓝二公子</td>
            <td>2019-03-01</td>
            <td><a th:href="@{/templates/member/detail}">详情</a></td>
        </tr>
        <tr>
            <td style="font-size: 20px;">魏无羡</td>
            <td>魔道祖师</td>
            <td>云梦江氏大弟子</td>
            <td>2019-03-02</td>
            <td><a th:href="@{/templates/member/detail}">详情</a></td>
        </tr>
        <tr>
            <td style="font-size: 20px;">苏沐橙</td>
            <td>枪炮师</td>
            <td>一流女玩家</td>
            <td>2019-03-03</td>
            <td><a th:href="@{/templates/member/detail}">详情</a></td>
        </tr>
    </table>
    </body>
    </html>
    

    到此用户管理服务也集成完毕了

    订单服务

    代码目录

    image.png

    1. Maven 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.3.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.glj</groupId>
        <artifactId>oauth2-sso-client-order</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>oauth2-sso-client-order</name>
        <description>订单服务</description>
    
        <properties>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-oauth2-client</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.security.oauth.boot</groupId>
                <artifactId>spring-security-oauth2-autoconfigure</artifactId>
                <version>2.1.3.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
            <dependency>
                <groupId>org.thymeleaf.extras</groupId>
                <artifactId>thymeleaf-extras-springsecurity5</artifactId>
                <version>3.0.4.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </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>
            </dependency>
    
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    

    2. application.yml

    server:
      port: 8083
      servlet:
        context-path: /orderSystem
    security:
      oauth2:
        client:
          client-id: OrderManagement
          client-secret: order123
          access-token-uri: http://127.0.0.1:8080/oauth/token
          user-authorization-uri: http://127.0.0.1:8080/oauth/authorize
        resource:
          jwt:
            key-uri: http://127.0.0.1:8080/oauth/token_key
    

    3. WebSecurityConfig 内容

    package com.glj.order.config;
    
    import com.glj.order.util.EnvironmentUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.builders.WebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    
    /**
     * @ClassName WebSecurityConfig
     * @Description TODO
     * @Author gaoleijie
     * @Date 2019/4/9 16:43
     **/
    @EnableOAuth2Sso
    @Configuration
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().antMatchers("/bootstrap/**");
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.logout().logoutSuccessUrl("http://127.0.0.1:8080/logout");
            http.authorizeRequests().anyRequest().authenticated();
            http.csrf().disable();
        }
    }
    

    4. OrderController 内容

    package com.glj.order.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    /**
     * @author gaoleijie
     * @date 2019-03-03
     */
    @Controller
    @RequestMapping("/order")
    public class OrderController {
    
        @GetMapping("/list")
        public String list() {
            return "order/list";
        }
    
    }
    

    5. Oauth2SsoClientOrderApplication 内容

    package com.glj.order;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class Oauth2SsoClientOrderApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(Oauth2SsoClientOrderApplication.class, args);
        }
    
    }
    

    6. list.html

    <!DOCTYPE html>
    <html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
    <head>
        <meta charset="UTF-8">
        <title>订单列表</title>
    </head>
    <body>
    <h3><span th:text="${#authentication.name}"></span> | <a th:href="@{/logout}">退出</a></h3>
    <h2>这是订单管理列表页面</h2>
    <h2><a href="http://127.0.0.1:8082/memberSystem/member/list">会员列表页面</a></h2>
    </body>
    </html>
    

    到此订单服务也集成完毕了。

    代码下载:

    相关文章

      网友评论

          本文标题:Oauth2.0 实现SSO单点登陆

          本文链接:https://www.haomeiwen.com/subject/gyxoiqtx.html