sso单点登录

2023-05-16

文章目录

目录

文章目录

前言

一、sso结构实现

二、使用步骤

2.1 建一个spring cloud 项目

 2.2 common下的core的配置

 2.3 实现系统的业务微服务

2.4 sso模块的编写  

总结



前言

单点登录(SingleSignOn,SSO),就是通过用户的一次性鉴别登录。当用户在身份认证服务器上登录一次以后,即可获得访问单点登录系统中其他关联系统和应用软件的权限,同时这种实现是不需要管理员对用户的登录状态或其他信息进行修改的,这意味着在多个应用系统中,用户只需一次登录就可以访问所有相互信任的应用系统。这种方式减少了由登录产生的时间消耗,辅助了用户管理,是比较流行的


一、sso结构实现

二、使用步骤

2.1 建一个spring cloud 项目

 在总的父工程下添加 父工程使用


2.3.12.RELEASE 的springboot项目创建 然后添加以下  
    <packaging>pom</packaging>
    <!--定义版本号-->
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF- 8</project.reporting.outputEncoding>
        <spring-cloud.version>Hoxton.SR8</spring-cloud.version>
        <spring-cloud-alibaba.version>2.2.3.RELEASE</spring-cloud-alibaba.version>
    </properties>
    <!--jar得管理 它只负责jar得管理不负责下载-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

其他二级模块和三级模块都是使用maven项目 每一个maven模块最后添加一个spring boot的启动类 

 2.2 common下的core的配置

引入依赖


<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
    <dependency>
        <groupId>com.auth0</groupId>
        <artifactId>java-jwt</artifactId>
        <version>3.18.3</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.83</version>
    </dependency>
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.2</version>
    </dependency>
</dependencies>  

添加实体类 工具类 

三个实体类 

@Data
@TableName(value = "cc_admin")
public class Admin implements Serializable {
    /**
     * 管理员表id
     */
    @TableId(value = "id",type = IdType.AUTO)
    private Integer id;

    /**
     * 管理员id
     */
    private String adminId;

    /**
     * 管理员用户名
     */
    private String adminUsername;

    /**
     * 管理员密码
     */
    private String adminPassword;

    /**
     * 管理员真实姓名
     */
    private String adminRealname;

    /**
     * 管理员密钥
     */
    private String salt;

    /**
     * 角色id
     */
    private String roleId;

    /**
     * 部门id
     */
    private String deptId;

    /**
     * 管理员性别
     */
    private String adminSex;

    /**
     * 管理员联系方式
     */
    private String adminTelephone;

    /**
     * 管理员年龄
     */
    private Integer adminAge;

    /**
     * 逻辑删除0(false)未删除,1(true)已删除
     */
    private Boolean isDeleted;

    /**
     * 创建时间
     */
    private Date gmtCreate;

    /**
     * 修改时间
     */
    private Date gmtModified;

    private static final long serialVersionUID = 1L;

    @Override
    public boolean equals(Object that) {
        if (this == that) {
            return true;
        }
        if (that == null) {
            return false;
        }
        if (getClass() != that.getClass()) {
            return false;
        }
        Admin other = (Admin) that;
        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
            && (this.getAdminId() == null ? other.getAdminId() == null : this.getAdminId().equals(other.getAdminId()))
            && (this.getAdminUsername() == null ? other.getAdminUsername() == null : this.getAdminUsername().equals(other.getAdminUsername()))
            && (this.getAdminPassword() == null ? other.getAdminPassword() == null : this.getAdminPassword().equals(other.getAdminPassword()))
            && (this.getAdminRealname() == null ? other.getAdminRealname() == null : this.getAdminRealname().equals(other.getAdminRealname()))
            && (this.getSalt() == null ? other.getSalt() == null : this.getSalt().equals(other.getSalt()))
            && (this.getRoleId() == null ? other.getRoleId() == null : this.getRoleId().equals(other.getRoleId()))
            && (this.getDeptId() == null ? other.getDeptId() == null : this.getDeptId().equals(other.getDeptId()))
            && (this.getAdminSex() == null ? other.getAdminSex() == null : this.getAdminSex().equals(other.getAdminSex()))
            && (this.getAdminTelephone() == null ? other.getAdminTelephone() == null : this.getAdminTelephone().equals(other.getAdminTelephone()))
            && (this.getAdminAge() == null ? other.getAdminAge() == null : this.getAdminAge().equals(other.getAdminAge()))
            && (this.getIsDeleted() == null ? other.getIsDeleted() == null : this.getIsDeleted().equals(other.getIsDeleted()))
            && (this.getGmtCreate() == null ? other.getGmtCreate() == null : this.getGmtCreate().equals(other.getGmtCreate()))
            && (this.getGmtModified() == null ? other.getGmtModified() == null : this.getGmtModified().equals(other.getGmtModified()));
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
        result = prime * result + ((getAdminId() == null) ? 0 : getAdminId().hashCode());
        result = prime * result + ((getAdminUsername() == null) ? 0 : getAdminUsername().hashCode());
        result = prime * result + ((getAdminPassword() == null) ? 0 : getAdminPassword().hashCode());
        result = prime * result + ((getAdminRealname() == null) ? 0 : getAdminRealname().hashCode());
        result = prime * result + ((getSalt() == null) ? 0 : getSalt().hashCode());
        result = prime * result + ((getRoleId() == null) ? 0 : getRoleId().hashCode());
        result = prime * result + ((getDeptId() == null) ? 0 : getDeptId().hashCode());
        result = prime * result + ((getAdminSex() == null) ? 0 : getAdminSex().hashCode());
        result = prime * result + ((getAdminTelephone() == null) ? 0 : getAdminTelephone().hashCode());
        result = prime * result + ((getAdminAge() == null) ? 0 : getAdminAge().hashCode());
        result = prime * result + ((getIsDeleted() == null) ? 0 : getIsDeleted().hashCode());
        result = prime * result + ((getGmtCreate() == null) ? 0 : getGmtCreate().hashCode());
        result = prime * result + ((getGmtModified() == null) ? 0 : getGmtModified().hashCode());
        return result;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(getClass().getSimpleName());
        sb.append(" [");
        sb.append("Hash = ").append(hashCode());
        sb.append(", id=").append(id);
        sb.append(", adminId=").append(adminId);
        sb.append(", adminUsername=").append(adminUsername);
        sb.append(", adminPassword=").append(adminPassword);
        sb.append(", adminRealname=").append(adminRealname);
        sb.append(", salt=").append(salt);
        sb.append(", roleId=").append(roleId);
        sb.append(", deptId=").append(deptId);
        sb.append(", adminSex=").append(adminSex);
        sb.append(", adminTelephone=").append(adminTelephone);
        sb.append(", adminAge=").append(adminAge);
        sb.append(", isDeleted=").append(isDeleted);
        sb.append(", gmtCreate=").append(gmtCreate);
        sb.append(", gmtModified=").append(gmtModified);
        sb.append(", serialVersionUID=").append(serialVersionUID);
        sb.append("]");
        return sb.toString();
    }
}

/**
 * 权限
 * @TableName cc_permission
 */
@Data
@TableName(value = "cc_permission")
public class Permission implements Serializable {
    /**
     * 编号
     */
    @TableId(value = "id")
    private String id;

    /**
     * 所属上级
     */
    private String pid;

    /**
     * 名称
     */
    private String name;

    /**
     * 类型(1:菜单,2:按钮)
     */
    private Integer type;

    /**
     * 权限值
     */
    private String permissionValue;

    /**
     * 访问路径
     */
    private String path;

    /**
     * 组件路径
     */
    private String component;

    /**
     * 图标
     */
    private String icon;

    /**
     * 状态(0:正常,1:禁用)
     */
    private Integer status;

    /**
     * 逻辑删除 1(true)已删除, 0(false)未删除
     */
    private Integer isDeleted;

    /**
     * 创建时间
     */
    private Date gmtCreate;

    /**
     * 更新时间
     */
    private Date gmtModified;

    private static final long serialVersionUID = 1L;

    @Override
    public boolean equals(Object that) {
        if (this == that) {
            return true;
        }
        if (that == null) {
            return false;
        }
        if (getClass() != that.getClass()) {
            return false;
        }
        Permission other = (Permission) that;
        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
            && (this.getPid() == null ? other.getPid() == null : this.getPid().equals(other.getPid()))
            && (this.getName() == null ? other.getName() == null : this.getName().equals(other.getName()))
            && (this.getType() == null ? other.getType() == null : this.getType().equals(other.getType()))
            && (this.getPermissionValue() == null ? other.getPermissionValue() == null : this.getPermissionValue().equals(other.getPermissionValue()))
            && (this.getPath() == null ? other.getPath() == null : this.getPath().equals(other.getPath()))
            && (this.getComponent() == null ? other.getComponent() == null : this.getComponent().equals(other.getComponent()))
            && (this.getIcon() == null ? other.getIcon() == null : this.getIcon().equals(other.getIcon()))
            && (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus()))
            && (this.getIsDeleted() == null ? other.getIsDeleted() == null : this.getIsDeleted().equals(other.getIsDeleted()))
            && (this.getGmtCreate() == null ? other.getGmtCreate() == null : this.getGmtCreate().equals(other.getGmtCreate()))
            && (this.getGmtModified() == null ? other.getGmtModified() == null : this.getGmtModified().equals(other.getGmtModified()));
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
        result = prime * result + ((getPid() == null) ? 0 : getPid().hashCode());
        result = prime * result + ((getName() == null) ? 0 : getName().hashCode());
        result = prime * result + ((getType() == null) ? 0 : getType().hashCode());
        result = prime * result + ((getPermissionValue() == null) ? 0 : getPermissionValue().hashCode());
        result = prime * result + ((getPath() == null) ? 0 : getPath().hashCode());
        result = prime * result + ((getComponent() == null) ? 0 : getComponent().hashCode());
        result = prime * result + ((getIcon() == null) ? 0 : getIcon().hashCode());
        result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode());
        result = prime * result + ((getIsDeleted() == null) ? 0 : getIsDeleted().hashCode());
        result = prime * result + ((getGmtCreate() == null) ? 0 : getGmtCreate().hashCode());
        result = prime * result + ((getGmtModified() == null) ? 0 : getGmtModified().hashCode());
        return result;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(getClass().getSimpleName());
        sb.append(" [");
        sb.append("Hash = ").append(hashCode());
        sb.append(", id=").append(id);
        sb.append(", pid=").append(pid);
        sb.append(", name=").append(name);
        sb.append(", type=").append(type);
        sb.append(", permissionValue=").append(permissionValue);
        sb.append(", path=").append(path);
        sb.append(", component=").append(component);
        sb.append(", icon=").append(icon);
        sb.append(", status=").append(status);
        sb.append(", isDeleted=").append(isDeleted);
        sb.append(", gmtCreate=").append(gmtCreate);
        sb.append(", gmtModified=").append(gmtModified);
        sb.append(", serialVersionUID=").append(serialVersionUID);
        sb.append("]");
        return sb.toString();
    }
}
@Data
@TableName(value = "cc_role")
public class Role implements Serializable {
    /**
     * 角色表id
     */
    @TableId(value = "id",type = IdType.AUTO)
    private Integer id;

    /**
     * 角色id
     */
    private String roleId;

    /**
     * 角色名称
     */
    private String roleName;

    /**
     * 角色描述
     */
    private String roleDescription;

    /**
     * 部门id
     */
    private String deptId;

    /**
     * 角色状态0(启用)1(禁用)
     */
    private Integer roleStatus;

    /**
     * 逻辑删除0(false)未删除,1(true)已删除
     */
    private Boolean isDeleted;

    /**
     * 创建时间
     */
    private Date gmtCreate;

    /**
     * 修改时间
     */
    private Date gmtModified;

    private static final long serialVersionUID = 1L;

    @Override
    public boolean equals(Object that) {
        if (this == that) {
            return true;
        }
        if (that == null) {
            return false;
        }
        if (getClass() != that.getClass()) {
            return false;
        }
        Role other = (Role) that;
        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
            && (this.getRoleId() == null ? other.getRoleId() == null : this.getRoleId().equals(other.getRoleId()))
            && (this.getRoleName() == null ? other.getRoleName() == null : this.getRoleName().equals(other.getRoleName()))
            && (this.getRoleDescription() == null ? other.getRoleDescription() == null : this.getRoleDescription().equals(other.getRoleDescription()))
            && (this.getDeptId() == null ? other.getDeptId() == null : this.getDeptId().equals(other.getDeptId()))
            && (this.getRoleStatus() == null ? other.getRoleStatus() == null : this.getRoleStatus().equals(other.getRoleStatus()))
            && (this.getIsDeleted() == null ? other.getIsDeleted() == null : this.getIsDeleted().equals(other.getIsDeleted()))
            && (this.getGmtCreate() == null ? other.getGmtCreate() == null : this.getGmtCreate().equals(other.getGmtCreate()))
            && (this.getGmtModified() == null ? other.getGmtModified() == null : this.getGmtModified().equals(other.getGmtModified()));
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
        result = prime * result + ((getRoleId() == null) ? 0 : getRoleId().hashCode());
        result = prime * result + ((getRoleName() == null) ? 0 : getRoleName().hashCode());
        result = prime * result + ((getRoleDescription() == null) ? 0 : getRoleDescription().hashCode());
        result = prime * result + ((getDeptId() == null) ? 0 : getDeptId().hashCode());
        result = prime * result + ((getRoleStatus() == null) ? 0 : getRoleStatus().hashCode());
        result = prime * result + ((getIsDeleted() == null) ? 0 : getIsDeleted().hashCode());
        result = prime * result + ((getGmtCreate() == null) ? 0 : getGmtCreate().hashCode());
        result = prime * result + ((getGmtModified() == null) ? 0 : getGmtModified().hashCode());
        return result;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(getClass().getSimpleName());
        sb.append(" [");
        sb.append("Hash = ").append(hashCode());
        sb.append(", id=").append(id);
        sb.append(", roleId=").append(roleId);
        sb.append(", roleName=").append(roleName);
        sb.append(", roleDescription=").append(roleDescription);
        sb.append(", deptId=").append(deptId);
        sb.append(", roleStatus=").append(roleStatus);
        sb.append(", isDeleted=").append(isDeleted);
        sb.append(", gmtCreate=").append(gmtCreate);
        sb.append(", gmtModified=").append(gmtModified);
        sb.append(", serialVersionUID=").append(serialVersionUID);
        sb.append("]");
        return sb.toString();
    }
}

jwt工具类和前端数据处理vo

public class JwtUtil {
    private static String sign="xxx";
    //1.生成jwt的token方法
    public static String createJWT(Map<String,Object> map){
        //定义头信息
        Map<String,Object> head= new HashMap<>();
        head.put("alg","HS256");
        head.put("typ","JWT");
        //定义颁发时间
        Date iat=new Date();
        //过期时间
        Calendar expire = Calendar.getInstance();
        expire.set(Calendar.SECOND,24*3600);//24*3600
        Date expireTime = expire.getTime();

        String token = JWT.create()
                //头信息
                .withHeader(head)
                //设置颁发时间
                .withIssuedAt(iat)
                //设置过期时间
                .withExpiresAt(expireTime)
                //自定义的内容
                .withClaim("userinfo",map)
                //签名
                .sign(Algorithm.HMAC256(sign));
        return token;
    }

    //2.校验token是否有效
    public static boolean verifyToken(String token){
        //获取一个JWT校验对象
        JWTVerifier build = JWT.require(Algorithm.HMAC256(sign)).build();
        try {
            //调用校验功能
            DecodedJWT verify = build.verify(token);
            return true;
        }catch (Exception e){
            System.out.println("token无效");
            return false;
        }

    }

    //3.从token中获取相关的载荷内容
    public static Map<String,Object> getTokenChaim(String token){
        //获取一个JWT校验对象
        JWTVerifier build = JWT.require(Algorithm.HMAC256(sign)).build();
        //调用校验功能
        DecodedJWT verify = build.verify(token);
        Claim loginInfo = verify.getClaim("userinfo");
        return loginInfo.asMap();
    }
}

vo 返回给前端的统一数据处理类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> {
    private Integer code;
    private String msg;
    private T data;

    public Result(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }
}

 2.3 实现系统的业务微服务

在modules添加需要的依赖

<dependencies>
        <dependency>
            <groupId>com.xin</groupId>
            <artifactId>xin-common-core</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>
<-- web启动类 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
<-- nacos注册中心 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
<-- 微服务之间的调用 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies>

在modules下新建system子模块 dao层和service使用mybatisX插件生成 启动类使用spring boot的

主要展示服务之间的控制层 

@RestController
@RequestMapping("system/permission")
public class PermissionController {
    @Autowired
    private PermissionService permissionService;

    @GetMapping("getPermissionByUserid/{userid}")
    public List<Permission> getPermissionByUserid(@PathVariable Integer userid){
         return permissionService.selectPermissionByUserid(userid);
    }
}
@RestController
@RequestMapping("system/admin")
public class AdminController {

    @Autowired
    private AdminService adminService;

    @GetMapping("/getByName/{name}")
    public Admin getByName(@PathVariable String name){
        QueryWrapper<Admin> wrapper=new QueryWrapper<>();
        wrapper.eq("admin_username",name);
        Admin admin = adminService.getOne(wrapper);
        return admin;
    }
}

配置文件

server.port=8087

spring.application.name=cai-system

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/caicai?serverTimezone=Asia/Shanghai
spring.datasource.password=root
spring.datasource.username=root

mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

spring.cloud.nacos.discovery.server-addr=localhost:8848

2.4 sso模块的编写  

添加依赖


<dependencies>
    <!--引入common-core-->
    <dependency>
        <groupId>com.xin</groupId>
        <artifactId>xin-common-core</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>

<-- rdis启动 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>
</dependencies>  

 

@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;

    @Autowired
    private StringRedisTemplate redisTemplate;
    @Bean
    public PasswordEncoder passwordEncoder() {
        //加盐加密: 原密码+盐===>哈希加密===>密文
        //   原密码===>哈希加密===>密文 [存储大量常见的密文]
        //123456+随机产生盐===>密文
        return new BCryptPasswordEncoder();
    }


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
                .successHandler(successHandler())
                .failureHandler(failureHandler())
                .loginProcessingUrl("/login").permitAll();

        http.cors();
        http.csrf().disable();
        http.authorizeRequests().anyRequest().authenticated();

    }

    private AuthenticationSuccessHandler successHandler() {
        return (request, response, authentication) -> {
            response.setContentType("application/json;charset=utf-8");
            PrintWriter writer = response.getWriter();
            //获取账号和权限
            String username = authentication.getPrincipal().toString();
            Collection<String> authorities = authentication.getAuthorities().stream().map(item->item.getAuthority()).collect(Collectors.toList());
            //根据账号和权限生产token;
            Map<String,Object> map=new HashMap<>();
            map.put("username",username);
            map.put("authorities",authorities);
            String token = JwtUtil.createJWT(map);

            //存入redis中。
            redisTemplate.opsForValue().set(token,"",30, TimeUnit.MINUTES);

            Result<String> result=new Result<>(2000,"登录成功",token);
            String jsonString = JSON.toJSONString(result);

            writer.print(jsonString);
            writer.flush();
            writer.close();
        };
    }

    private AuthenticationFailureHandler failureHandler() {
        return (request, response, e) -> {
            response.setContentType("application/json;charset=utf-8");
            PrintWriter writer = response.getWriter();

            Result<String> result=new Result<>(5000,"登录失败");
            String jsonString = JSON.toJSONString(result);

            writer.print(jsonString);
            writer.flush();
            writer.close();
        };
    }

    public static void main(String[] args) {
        BCryptPasswordEncoder passwordEncoder=new BCryptPasswordEncoder();
        System.out.println(passwordEncoder.encode("123456"));
    }
}

两个微服务的调用 


@FeignClient(value = "cai-system")
public interface AdminFeign {
    //建议:如果是服务之间的调用直接返回对象,如果是前端调用CommonResult
    @GetMapping("/system/admin/getByName/{name}")
    public Admin getByName(@PathVariable String name);
}

@FeignClient(value = "cai-system")
public interface PermissionFeign {

    @GetMapping("/system/permission/getPermissionByUserid/{userid}")
    public List<Permission> getPermissionByUserid(@PathVariable Integer userid);
}

自定义登录规则


@Service
public class UserService implements UserDetailsService {
    @Autowired
    private AdminFeign adminFeign;
    @Autowired
    private PermissionFeign permissionFeign;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //1.根据用户名查询用户信息
        Admin admin = adminFeign.getByName(username);
        if(admin!=null){
            //2.根据当前用户查询该用户具有的权限。
            List<Permission> permissions = permissionFeign.getPermissionByUserid(admin.getId());
            Collection<SimpleGrantedAuthority> authorities = permissions.stream().filter(item->item.getPermissionValue()!=null).filter(item->item.getType()==2).map(item->new SimpleGrantedAuthority(item.getPermissionValue())).collect(Collectors.toList());
            User user = new User(admin.getAdminUsername(),admin.getAdminPassword(),authorities);
            return user;
        }
        return null;
    }
}

主启动类


/**
 * 排除多余的自动装配类可开启openfeign
 */
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableFeignClients
public class SsoApp {
    public static void main(String[] args) {
        SpringApplication.run(SsoApp.class,args);
    }
}

配置文件application.properties

server.port=8088

spring.application.name=cai-sso

spring.cloud.nacos.discovery.server-addr=localhost:8848

spring.redis.host=localhost
spring.redis.port=6379

#解决多个FeignClientSpecification' could not be registered
#开启重写多个feign接口
spring.main.allow-bean-definition-overriding=true

 这样SSo模块就完成了


总结

待补充

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

sso单点登录 的相关文章

  • 对比应用层和内核层区别

    1 应用层和内核层是计算机系统中的两个不同的层次 应用层是用户直接与计算机系统交互的层次 xff0c 它包括各种APP和libc xff08 Linux下的ANSI C的函数库 xff09 内核层是计算机系统的核心 xff0c 它提供了各种
  • uc/OS-III移植到stm32f103c8进行多任务实验

    文章目录 一 UCOSIII介绍1 简介2 UCOSIII中的任务 二 将uc OS III移植到stm32f103c81 创建CubeMx工程2 进行uCOS III的移植 三 构建三个任务1 代码添加 四 结果展示五 总结五 参考链接
  • Invalid bound statement (not found)出现原因和解决方法

    Invalid bound statement not found 出现原因和解决方法 出现的原因 xff1a mapper接口和mapper xml文件没有映射起来 解决方法 xff1a 1 mapper xml中的namespace和实
  • 服务器磁盘满了会导致ssl无法正常访问,进而导致网站样式错乱

    服务器磁盘满了会导致ssl无法正常访问 xff0c 进而导致网站样式错乱
  • 基于OpenMV和正点原子开发的自动追球小车(带云台舵机)

    电赛备赛前 xff0c 通过OpenMV加舵机云平台由 xff0c 做了一个追着球跑的小车 xff0c 由于疫情 xff0c 以前录制的视频也删除了 xff0c 最终呈现的效果和B站一位Up主的相似 xff0c 大家可以参考参考 xff0c
  • C语言For循环

    循环结构 xff1a 又称为重复结构 xff0c 在程序中处理问题需要重复处理 for循环语句 xff1a 使用灵活 可用于循环次数已确定或不确定循环次数的情况 for循环的一般结构 xff1a for xff08 表达式1 xff1b 表
  • Jetson tx2 安装jetpack_3.3手动安装cuda9.0,cudnn7.1

    1 刷机前的准备 xff08 写在前面的话 xff09 装有Ubuntu16 04或者Ubuntu18 04的电脑 xff0c 这里说的电脑可以是台式机也可以是笔记本与TX2区分开来 xff08 电脑是16 04或者18 04无所谓 xff
  • 【PX4无人机仿真】构建自己的ROS节点

    本篇文章主要是一个创建自己的ros节点的学习记录 xff0c 在学会创建简单的节点后 xff0c 参考一篇关于目标跟踪工作的博客进行了实践 xff0c 使用自己写的移动小球世界进行小球的跟踪 Demo参考 xff1a 无人机跟踪小车 文章目
  • 用U盘给nuc安装Ubuntu系统

    1 在Windows下载对应Linux的软件 xff08 一般为UNetbootin xff09 2 网上下载所需Ubuntu版本的iso文件 3 准备一个内存大于4g的U盘 4 双击运行第一步下载的软件 5 更改光盘镜像 xff0c 选择
  • keil5下载安装教程(附带兼容keil4方法)

    为了方便stm32和C51学习 xff0c 我收集资料整理了keil5的安装教程 xff0c 同时附带兼容keil4程序的方法 xff0c 避免大家在使用C51的时候再去安装keil4这个麻烦的过程 目录 一 可兼容keil4的keil5版
  • 第十三届蓝桥杯单片机设计与开发

    程序设计 客观题 感想 xff1a 这届单片机还是挺简单的 xff0c 和前几届的赛题有点像 xff0c 哦 xff0c 对 xff0c 就是第12届和第10届来着 大概2个半小时差不多全做完了 xff1b 当然客观题 xff0c 有几道不
  • PX4串口添加传感器—在QGC上添加串口数据显示

    前言 因为项目要求 xff0c xff08 在PX4上添加拉力传感器 xff0c 并把数据显示在QGC的地图上 xff09 xff0c 本人开始了苦皮的生活 从未接触飞控的我 xff0c 一来就是开发 烧脑掉发啊 但人生是无所畏惧的 在学习
  • STM32CubeMX——固件库下载以及安装

    前言 为了方便自己 xff0c 于是方便了大家 一 获取stm32Cube包 1 打开下面的链接 ST官网链接 2 下载stm32标准外设库 我要用STMCubeG413rbt6 xff0c 所以我选择STM32CubeG4系列 点击 点击
  • PX4串口添加传感器—QGC添加自定义mavlik消息

    简介 功能 xff1a 假设我想要飞控传输一个我定义的消息给地面站 xff0c 其地面站必须有一个接收处理的过程以及飞控处理发送的过程 我们传输的方式是mavlink通信方式 想要实现上面的功能 xff0c PX4和QGC就必须要有 1 修
  • 服务器扩容步骤

    第一步 xff1a 云服务器 ECS 云盘 扩容 勾选在线扩容 xff0c 提交订单 xff1b 第二步 xff1a 以此执行以下代码 xff1a 1 运行fdisk l命令查看现有云盘大小 root 64 ecshost fdisk l
  • PX4串口添加传感器—PX4添加自定义mavlik消息

    目录 1 建立 xml并生成mavlink自定义消息文件 1 1 打开终端克隆MAVLINK生成器 1 2 进入克隆目录 执行以下命令 1 3 随手建立储存文件夹 1 4 创建read uart sensor xml文件 1 5 打开MAV
  • 丢失ucrtbased.dll,缺啥补啥

    简介 xff1a 当我打包QGC的debug版本给别人 结果别人编译不了 xff0c 内容显示缺少ucrtbased dll文件 发现一个不错的网站 xff0c 缺少其他文件 xff0c 一样的方法 解决办法 xff1a 打开链接 xff1
  • 打开QGC软件主页没有显示,弹窗白板问题

    目录 问题描述 解决办法 问题描述 正常情况下 xff0c QGC打开是直接就弹出显示页面 但当我打开编译过的debug版本QGC xff0c 会出现一个大约1秒的弹窗 xff0c 之后QGC没有显示 我在旁边的任务栏中查看 xff0c 发
  • Ubuntu/Linux文件权限修改

    Ubuntu Linux文件权限 文件权限是指不同的用户或用户组对某个文件拥有的权限 xff0c 文件的权限分为三种 xff1a r xff1a 读 w xff1a 写 x xff1a 可执行 文件描述形式如下 xff1a rw rw r
  • RTOS必备基础

    RTOS必备基础 一 ARM基础知识1 ARM架构2 重要寄存器3 汇编指令详解读 xff1a load写 store加 ADD减 SUB出栈 push出栈 xff1a pop 4 栈和堆 xff1a 1 栈2 堆 5 局部变量和全局变量的

随机推荐

  • STM32必备知识点(面试和工作用的到)

    STM32必备知识点 xff08 面试和工作用的到 xff09 文章目录 STM32必备知识点 xff08 面试和工作用的到 xff09 前言嵌入式C基础一 位操作1 不改变其他位的值的状况下 xff0c 对某几个位进行设值2 移位操作提高
  • 嵌入式C语言必备知识(面试和工作都用得到)

    嵌入式C语言必备知识 xff08 面试和工作都用得到 xff09 一 基础部分1 数组与链表的区别 xff1f 2 C语言程序代码优化方法3 堆和栈的的区别 xff1f 4 内联函数的优缺点和适用场景是什么 xff1f 4 下面代码输出是什
  • SBUS协议介绍和标准例程

    SBUS信号例程详解 1 SBUS信号简介1 硬件标准2 软件标准1 串口配置 xff1a 2 协议格式 xff1a 3 数据范围4 间隔问题 2 STM32F4 Sbus xff08 DMA 43 串口 xff09 xff08 1 xff
  • RT-Thread静态线程和动态线程的区别

    RT Thread 内核采用面向对象的设计思想进行设计 xff0c 系统级的基础设施都是一种内核对象 xff0c 例如线程 xff0c 信号量 xff0c 互斥量 xff0c 定时器等 内核对象分为两类 xff1a 静态内核对象和动态内核对
  • UART协议入门

    UART 硬件连接关键词 xff1a 1 UART为串行异步协议2 TTL RS232 RS485是一种逻辑电平表示方式 3 帧格式 xff1a 1位空闲位 xff0c 5 9位的数据位 xff0c 1位校验位 xff0c 1 2位的停止位
  • git操作手册

    初始化一个Git仓库 xff0c 使用git init命令 添加文件到Git仓库 xff0c 分两步 xff1a 使用命令git add lt file gt xff0c 注意 xff0c 可反复多次使用 xff0c 添加多个文件 xff1
  • STM32 开发常见问题汇总

    STM32 开发常见问题汇总 一 xff0c STM32 Usart 串口异常四个错误检测标志 xff1a 十个具有标志位的中断源 xff1a 1 Usart中断事件2 Usart状态寄存器3 Usart问题解决3 1 什么是ORE中断 x
  • Gitee克隆别人的仓库的操作步骤

    1 指定克隆仓库路径 以及克隆到本地项目自定义名称 可以克隆提交者配置的url映射 但是不能克隆提交者的账号 git config git clone https gitee com lisi giteedemo giteedemo 2 配
  • c++八数码难题全家桶(A*算法、双向BFS、BFS、DFS)

    文章目录 系列文章目录前言 目录 系列文章目录 文章目录 前言 一 八数码难题是什么 xff1f 二 算法详解 1 首先利用逆序数来判断是否有解 xff08 奇偶性相同即可达 xff09 2 A 算法 3 双向BFS 4 BFS 5 DFS
  • Horspool (String Matching)

    Description of Horspool Assumation text string the string where we want to locate the pattern string n the length of the
  • C语言课程设计学生成绩管理系统二(含完整代码)

    亲给个打赏吧 1 系统功能 xff08 1 xff09 通过菜单的形式实现人机交互界面 xff08 2 xff09 实现录入学生基本信息和成绩功能 xff08 3 xff09 实现删除指定学生的基本信息和成绩功能 xff08 4 xff09
  • UNIX环境高级编程笔记

    UNIX环境编程 一 UNIX基础知识1 1 Linux 主要特性1 2 Linux 内核1 3 Linux 目录结构1 4 登录1 登录名2 shell 1 5 输入和输出1 文件描述符2 标准输入 标准输出 标准错误3 不带缓冲的IO4
  • 使用TensorFlow Serving进行模型的部署和客户端推理

    目的 xff1a 在一个server端使用TensorFlow框架对模型进行训练和保存模型文件后用TensorFlow Serving进行部署 xff0c 使得能在客户端上传输入数据后得到server端返回的结果 xff0c 实现远程调用的
  • spring boot自动打开浏览器和配置打开首页

    目录 前言 一 配置自动打开浏览器 在启动器同级目录下创建config文件夹来放启动配置类 下面是application properties的配置 二 配置默认首页 总结 前言 如何配置自动打开浏览器 和默认页面设置 一 配置自动打开浏览
  • 使用内网穿透工具natapp

    一 使用准备 1 进入他的官网注册一个账号 NATAPP 内网穿透 基于ngrok的国内高速内网映射工具 注意 这个账号还必须要提交实名认证 2 然后登陆进去 选择 购买隧道 gt 免费隧道 然后最重要的是配置一下免费隧道的协议 选择web
  • 在linux下安装docker

    文章目录 目录 文章目录 前言 一 docker 二 使用步骤 1 环境准备 2 安装 三 配置阿里云镜像加速 四 卸载 总结 前言 一 docker 镜像 xff08 image xff09 xff1a docker镜像就好比是一个模板
  • git分支管理开发

    1 master从来都只是最终合并的分支 xff1b 2 所有的其他分支都从master衍生 xff1b 3 在master分支直接修改 xff0c 有可能会造成所有分支的冲突 4 都是从master建立新分支 xff0c 修改测试通过后合
  • Docker的常用命令

    文章目录 目录 文章目录 前言 一 帮助命令 二 镜像命令 1 查看镜像 2 搜索镜像 3 下载镜像 4 删除镜像 三 容器命令 1 启动容器 2 查看容器 3 退出容器 4 删除容器 5 启动和停止容器 四 常用的其它命令 后台运行 查看
  • spring cloud gateway网关和链路监控

    文章目录 目录 文章目录 前言 一 网关 1 1 gateway介绍 1 2 如何使用gateway 1 3 网关优化 1 4自定义断言和过滤器 1 4 1 自定义断言 二 Sleuth 链路追踪 2 1 链路追踪介绍 2 2 Sleuth
  • sso单点登录

    文章目录 目录 文章目录 前言 一 sso结构实现 二 使用步骤 2 1 建一个spring cloud 项目 2 2 common下的core的配置 2 3 实现系统的业务微服务 2 4 sso模块的编写 总结 前言 单点登录 Singl