Oauth2.0 实现SSO单点登陆

2019-04-10  本文已影响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>

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

代码下载:

上一篇 下一篇

猜你喜欢

热点阅读