实现单点登录

让认证和授权走数据库

package ml.yompc.myshop.plus.business.service;

import com.google.common.collect.Lists;
import ml.yompc.myshop.plus.provider.api.UmsAdminService;
import ml.yompc.myshop.plus.provider.domain.UmsAdmin;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.security.core.GrantedAuthority;
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.stereotype.Component;

import java.util.List;

/**
 * @email yom535@outlook.com
 * @author: 有民(yom535)
 * @date: 2019/9/27
 * @time: 23:48
 */
@Component
public class UserDetailsServiceImpl implements UserDetailsService {

    @Reference(version = "1.0.0")
    private UmsAdminService umsAdminService;


    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        //给每个用户授权USER权限
        List<GrantedAuthority> grantedAuthorities= Lists.newArrayList();
        GrantedAuthority grantedAuthority=new SimpleGrantedAuthority("USER");
        grantedAuthorities.add(grantedAuthority);

        UmsAdmin umsAdmin = umsAdminService.get(username);
        if (umsAdmin != null)
        {
            //账号存在
            return new User(umsAdmin.getUsername(),umsAdmin.getPassword(),grantedAuthorities);
        }
        else
        {
            //账号不存在
            return null;
        }

    }
}

记得配置dubbo扫描包

dubbo:
  scan:
    base-packages: ml.yompc.myshop.plus.business.controller, ml.yompc.myshop.plus.business.service

创建个人信息服务usiness-profile

POM

<?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>ml.yompc.myshop.plus</groupId>
        <artifactId>business</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <artifactId>business-profile</artifactId>
    <packaging>pom</packaging>
    <url>http://www.yompc.ml</url>
    <inceptionYear>2018-Now</inceptionYear>

    <licenses>
        <license>
            <name>Apache 2.0</name>
            <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
        </license>
    </licenses>

    <developers>
        <developer>
            <id>yompc</id>
            <name>FengJia Liu</name>
            <email>yom535@outlook.com</email>
        </developer>
    </developers>

    <modules>
        <module>business-profile-feign</module>
        <module>business-profile-service</module>
    </modules>
</project>

创建business-profile-feign

<?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>ml.yompc.myshop.plus</groupId>
        <artifactId>business-profile</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <artifactId>business-profile-feign</artifactId>
    <packaging>jar</packaging>
    <url>http://www.yompc.ml</url>
    <inceptionYear>2018-Now</inceptionYear>

    <licenses>
        <license>
            <name>Apache 2.0</name>
            <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
        </license>
    </licenses>

    <developers>
        <developer>
            <id>yompc</id>
            <name>FengJia Liu</name>
            <email>yom535@outlook.com</email>
        </developer>
    </developers>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>ml.yompc.myshop.plus</groupId>
            <artifactId>configuration-feign</artifactId>
            <version>${project.parent.version}</version>
            <scope>provided</scope>
        </dependency>

    </dependencies>
</project>

创建business-profile-service

<?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>ml.yompc.myshop.plus</groupId>
        <artifactId>business-profile</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <artifactId>business-profile-service</artifactId>
    <packaging>jar</packaging>
    <url>http://www.yompc.ml</url>
    <inceptionYear>2018-Now</inceptionYear>

    <licenses>
        <license>
            <name>Apache 2.0</name>
            <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
        </license>
    </licenses>

    <developers>
        <developer>
            <id>yompc</id>
            <name>FengJia Liu</name>
            <email>yom535@outlook.com</email>
        </developer>
    </developers>

    <dependencies>
        <!-- Spring Boot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- Spring Cloud -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>

        <!-- Spring Cloud Alibaba -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <!-- Apache Dubbo -->
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-registry-nacos</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>javax.servlet</groupId>
                    <artifactId>servlet-api</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-serialization-kryo</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.apache.dubbo</groupId>
                    <artifactId>dubbo-common</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.alibaba.spring</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>

        <!-- Projects -->
        <dependency>
            <groupId>ml.yompc.myshop.plus</groupId>
            <artifactId>commons-dto</artifactId>
            <version>${project.parent.version}</version>
        </dependency>
        <dependency>
            <groupId>ml.yompc.myshop.plus</groupId>
            <artifactId>commons-utils</artifactId>
            <version>${project.parent.version}</version>
        </dependency>
        <dependency>
            <groupId>ml.yompc.myshop.plus</groupId>
            <artifactId>business-profile-feign</artifactId>
            <version>${project.parent.version}</version>
        </dependency>
        <dependency>
            <groupId>ml.yompc.myshop.plus</groupId>
            <artifactId>ums-admin-provider-api</artifactId>
            <version>${project.parent.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>ml.yompc.myshop.plus.business.BusinessProfileApplication</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

APPlication

package ml.yompc.myshop.plus.business;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

/**
 * @email yom535@outlook.com
 * @author: 有民(yom535)
 * @date: 2019/10/20
 * @time: 14:03
 */
@SpringBootApplication
@EnableDiscoveryClient
public class BusinessProfileApplication {
    public static void main(String[] args) {
        SpringApplication.run(BusinessProfileApplication.class,args);
    }
}

配置资源服务器

package ml.yompc.myshop.plus.business.configure;

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;

/**
 * @email yom535@outlook.com
 * @author: 有民(yom535)
 * @date: 2019/10/20
 * @time: 14:18
 */
@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true,jsr250Enabled = true)
public class ProfileResourceServerConfiguration 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("/**").hasAuthority("USER");
    }

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

Contrller视图层

package ml.yompc.myshop.plus.business.controller;

import ml.yompc.myshop.plus.commons.dto.ResponseResult;
import ml.yompc.myshop.plus.provider.api.UmsAdminService;
import ml.yompc.myshop.plus.provider.domain.UmsAdmin;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**个人信息管理
 * @email yom535@outlook.com
 * @author: 有民(yom535)
 * @date: 2019/10/20
 * @time: 14:07
 */
@RestController
@RequestMapping(value = "/profile")
public class ProfileController {

    @Reference(version = "1.0.0")
    private UmsAdminService umsAdminService;

    @GetMapping(value = "info/{username}")
    public ResponseResult<UmsAdmin> info(@PathVariable String username)
    {
        UmsAdmin umsAdmin = umsAdminService.get(username);

        return new ResponseResult<UmsAdmin>(ResponseResult.CodeStatus.OK,"查询用户信息",umsAdmin);
    }

}

application.yml

base:
  config:
    oauth:
      hostname: localhost
      port: 9001
    nacos:
      hostname: nacos.yompc.ml
      port: 80

spring:
  application:
    name: business-profile
  main:
    allow-bean-definition-overriding: true
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss
  cloud:
    nacos:
      discovery:
        server-addr: ${base.config.nacos.hostname}:${base.config.nacos.port}

security:
  oauth2:
    client:
      client-id: client
      client-secret: secret
      access-token-uri: http://${base.config.oauth.hostname}:${base.config.oauth.port}/oauth/token
      user-authorization-uri: http://${base.config.oauth.hostname}:${base.config.oauth.port}/oauth/authorize
    resource:
      token-info-uri: http://${base.config.oauth.hostname}:${base.config.oauth.port}/oauth/check_token

dubbo:
  scan:
    base-packages: ml.yompc.myshop.plus.business.controller
  protocol:
    name: dubbo
    port: -1
    serialization: kryo
  registry:
    address: nacos://${base.config.nacos.hostname}
    port: ${base.config.nacos.port}

server:
  port: 9002

management:
  endpoints:
    web:
      exposure:
        include: "*"

开启Feign

package ml.yompc.myshop.plus.business.feign;

import ml.yompc.myshop.plus.configuration.FeignRequestConfiguration;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * @email yom535@outlook.com
 * @author: 有民(yom535)
 * @date: 2019/10/20
 * @time: 14:14
 */
@FeignClient(value = "business-profile",path = "profile",configuration = FeignRequestConfiguration.class)
public interface ProfileFeign {

    @GetMapping(value = "info/{username}")
    String info(@PathVariable String username);

}

新建通用配置模块configuration

<?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>ml.yompc.myshop.plus</groupId>
        <artifactId>parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <artifactId>configuration</artifactId>
    <packaging>pom</packaging>
    <url>http://www.yompc.ml</url>
    <inceptionYear>2018-Now</inceptionYear>

    <licenses>
        <license>
            <name>Apache 2.0</name>
            <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
        </license>
    </licenses>

    <developers>
        <developer>
            <id>yompc</id>
            <name>FengJia Liu</name>
            <email>yom535@outlook.com</email>
        </developer>
    </developers>

    <modules>
        <module>configuration-feign</module>
    </modules>
</project>

配置Feign

<?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>ml.yompc.myshop.plus</groupId>
        <artifactId>configuration</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <artifactId>configuration-feign</artifactId>
    <packaging>jar</packaging>
    <url>http://www.yompc.ml</url>
    <inceptionYear>2018-Now</inceptionYear>

    <licenses>
        <license>
            <name>Apache 2.0</name>
            <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
        </license>
    </licenses>

    <developers>
        <developer>
            <id>yompc</id>
            <name>FengJia Liu</name>
            <email>yom535@outlook.com</email>
        </developer>
    </developers>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>

配置bean

package ml.yompc.myshop.plus.configuration;

import feign.RequestInterceptor;
import ml.yompc.myshop.plus.interceptor.FeignRequestInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @email yom535@outlook.com
 * @author: 有民(yom535)
 * @date: 2019/10/21
 * @time: 0:08
 */
@Configuration
public class FeignRequestConfiguration {
    @Bean
    public RequestInterceptor requestInterceptor() {
        return new FeignRequestInterceptor();
    }
}

配置Feign带请求头

package ml.yompc.myshop.plus.interceptor;
import feign.Request;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.nio.charset.Charset;
import java.util.Enumeration;
/**
 * @email yom535@outlook.com
 * @author: 有民(yom535)
 * @date: 2019/10/20
 * @time: 23:58
 */
public class FeignRequestInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert attributes != null;
        HttpServletRequest request = attributes.getRequest();

        // 设置请求头
        Enumeration<String> headerNames = request.getHeaderNames();
        if (headerNames != null) {
            while (headerNames.hasMoreElements()) {
                String name = headerNames.nextElement();
                String value = request.getHeader(name);
                requestTemplate.header(name, value);
            }
        }

        // 设置请求体,这里主要是为了传递 access_token
        Enumeration<String> parameterNames = request.getParameterNames();
        StringBuilder body = new StringBuilder();
        if (parameterNames != null) {
            while (parameterNames.hasMoreElements()) {
                String name = parameterNames.nextElement();
                String value = request.getParameter(name);

                // 将 Token 加入请求头
                if ("access_token".equals(name)) {
                    requestTemplate.header("authorization", "Bearer " + value);
                }

                // 其它参数加入请求体
                else {
                    body.append(name).append("=").append(value).append("&");
                }
            }
        }

        // 设置请求体
        if (body.length() > 0) {
            // 去掉最后一位 & 符号
            body.deleteCharAt(body.length() - 1);
            requestTemplate.body(Request.Body.bodyTemplate(body.toString(), Charset.defaultCharset()));
        }
    }
}

记得在之前的ml.yompc.myshop.plus.business.feign.ProfileFeign接口中FeignClient添加

configuration = FeignRequestConfiguration.class

package ml.yompc.myshop.plus.business.feign;

import ml.yompc.myshop.plus.configuration.FeignRequestConfiguration;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * @email yom535@outlook.com
 * @author: 有民(yom535)
 * @date: 2019/10/20
 * @time: 14:14
 */
@FeignClient(value = "business-profile",path = "profile",configuration = FeignRequestConfiguration.class)
public interface ProfileFeign {

    @GetMapping(value = "info/{username}")
    String info(@PathVariable String username);

}

在消费者开启okhttp-feign

application.yml

feign:
  okhttp:
    enabled: true
  httpclient:
    enabled: false

dependency

		<dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-okhttp</artifactId>
        </dependency>

解决Json日期转换问题

配置文件application.yml

spring:
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss

并在实体类中加入@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Column(name = "create_time")
    private Date createTime;

    /**
     * 最后登录时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Column(name = "login_time")
    private Date loginTime;

PostMan测试

1571673772718