sso单点登录

news2024/11/28 8:32:04

文章目录

目录

文章目录

前言

一、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模块就完成了

 

 

 

 

 

 

 

 

 

 

 


总结

待补充

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/364278.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

复习知识点三:做人不能半途而废,就算躺平也要躺最舒服的那张床

目录 运算符​编辑 键盘录入: 练习:键盘输入数字并求和 练习: 算术运算符 隐式转换(自动类型提升) 强制转换 练习1: 字符串的 "" 操作 ​编辑 练习 1: 练习2: 练习3: 自增自减运算符 赋值运算符 关系运算符(比较运算符)的分类 练习: 逻辑运算符 短路逻辑运…

电商平台销量查询:2023年1月牛奶乳品热门排行榜

随着人们消费能力的提升以及健康意识的增强&#xff0c;牛奶乳品已经成为居民日常饮食中的重要组成部分&#xff0c;伴随人们整体消费的增长&#xff0c;牛奶乳品行业也越来越成熟。 今年1月份我国牛奶乳品行业的整体趋势如何呢&#xff1f;结合数据我们一同来分析&#xff01;…

国外博士后待遇情况汇总

许多老师再考虑申请国外博士后的时候会顾虑待遇方面的问题&#xff0c;对此知识人网小编整理关于主要国家博士后待遇情况的汇总。美国&#xff1a;美国机会更多&#xff0c;生活质量更高&#xff0c;生活空间也广。美国的年薪一般是3.0-6.5万美金左右&#xff0c;刚博士毕业出来…

无脑霸总漫开播,她穿书变成恶毒女配,本想和霸总离婚摆烂

无脑霸总漫开播&#xff0c;她穿书变成恶毒女配&#xff01;本想和霸总离婚摆烂&#xff0c;不料却被霸总盯上了&#xff5e;虐妻一时爽&#xff0c;追妻火葬场&#xff0c;曾经的我你爱搭不理&#xff0c;现在的我你高攀不起&#xff01;#无脑霸总漫开播 #如何在无脑霸总漫里艰…

Sql Server数据库实现表中字段的列加密研究

1、问题描述 去年6月份的时候做过一个薪酬系统&#xff0c;要对里面的一些敏感字段进行一下加密。Sqlserver列加密可以参考官方文档&#xff1a;SQL Server 技术文档 - SQL Server | Microsoft Learn。主要看下来有三种加密方法&#xff1a;1、利用证书对数据进行加密和解密。2…

Google Guice 3:Bindings(1)

1. 序言 上一篇博客&#xff0c;《Google Guice 2&#xff1a;Mental Model》&#xff0c;讲述了Guice的建模思路&#xff1a;Guice is a map Guice官网认为&#xff1a;binding是一个对象&#xff0c;它对应Guice map中的一个entry&#xff0c;通过创建binding就可以向Guice …

RocketMQTemplate 实现消息发送

代码托管于gitee&#xff1a;easy-rocketmq 文章目录一、前置工作二、消费者三、生产者1. 普通消息2. 过滤消息3. 同步消息4. 延时消息5. 批量消息6. 异步消息7. 单向消息8. 顺序消息9. 事务消息概要Demo源码解读一、前置工作 1、导入依赖 <dependency><groupId>…

《羊驼亡命跑》 NFT 系列:羊驼跑酷套装来袭!

完美的羊驼跑酷&#xff01;这一系列植物、平台、愤怒的农民和神秘物品与你们的 Alpacadabraz 化身都是绝配。 关于 Paca Death Run Alpacadabraz 团队推出的首个主要体验的一切都很吸引&#xff01;这款跑酷游戏垂直填满了一个整个 1x1 The Sandbox LAND&#xff0c;挑战玩家在…

扬帆优配|看多A股!多家外资高调发声

外资看多我国的声响和动作正在增多&#xff01; A股商场迎来全面注册制落地后的首个交易日&#xff0c;三大指数集体走强。业内人士分析称&#xff0c;跟着全面实行股票发行注册制改革正式发动&#xff0c;能够预见&#xff0c;跟着商场化程度逐步进步&#xff0c;外资布局我国…

每天五分钟机器学习:新的大规模的机器学习机制——在线学习机制

本文重点 本节课程我们将学习一种新的大规模的机器学习机制--在线学习机制。在线学习机制让我们可以模型化问题。在线学习算法指的是对数据流进行学习而非离线的静态数据集的学习。许多在线网站都有持续不断的用户流,对于每一个用户,网站希望能在不将数据存储到数据库中便顺…

【Mybatis源码分析】datasource配置${}表达式时是如何被解析的?

核心配置中${}表达式配置的解析一、核心配置主体二、核心配置文件中properties是如何被解析的&#xff1f;三、${} 表达式的解析四、总结前提&#xff1a; 核心配置文件是被XMLConfigBuilder 对象进行解析的&#xff0c;configuration 对象是由它父类BaseBuider继承下来的属性…

LQB10,AT24C02的使用

1、单片机用P20和P21和AT24C02通信&#xff1b; 2、比赛提供的开发包里面的代码。 头文件 c文件 提供的代码解读以及修改合适自己使用。 #ifndef _IIC_H #define _IIC_Hvoid IIC_Start(void); void IIC_Stop(void); bit IIC_WaitAck(void); void IIC_SendAck(bit …

产品经理考个 PMP 有用吗?

产品经理考PMP肯定是有用的。学无止境&#xff01; 这里给一些想要转行项目管理的朋友一些PMP考证资料分享&#xff0c;内含不少考纲知识&#xff0c;题库&#xff0c;解题技巧&#xff0c;思维导图等等&#xff0c;有需要就保存下来&#xff0c;留着下次需要的时候用。 一&a…

二、并发编程的三大特性

文章目录并发编程的三大特性1、原子性什么是并发编程的原子性&#xff1f;保证并发编程的原子性synchronizedCASLock锁ThreadLocal2、可见性什么是可见性?解决可见性的方式volatilesynchronizedLockfinal3、有序性什么是有序性?as-if-serialhappens-beforevolatile并发编程的…

谷歌seo新站如何快速排名?如何提高Google自然排名

本文主要分享谷歌SEO如何做新站排名&#xff0c;很多刚出海的外贸小伙伴不会做谷歌SEO&#xff0c;快来学习。 本文由光算创作&#xff0c;有可能会被剽窃和修改&#xff0c;我们佛系对待这种行为吧。 谷歌seo新站如何快速排名&#xff1f; 答案是&#xff1a;大量优质原创内…

科技新浪推前浪 ChatGPT将元宇宙“拍在沙滩上”?

近期ChatGPT的热度显然已经盖过了元宇宙&#xff0c;回想去年元宇宙大热之际&#xff0c;很多企业纷纷跟进&#xff0c;甚至还有不少公司选择更名以表达All In元宇宙的决心。而如今ChatGPT抢占风头&#xff0c;成为新宠&#xff0c;元宇宙似乎被“抛弃”了&#xff0c;难道元宇…

VCL界面组件DevExpress VCL v22.2 - 拥有全新的矢量图形

DevExpress VCL是Devexpress公司旗下最老牌的用户界面套包&#xff0c;所包含的控件有&#xff1a;数据录入、图表、数据分析、导航、布局等。该控件能帮助您创建优异的用户体验&#xff0c;提供高影响力的业务解决方案&#xff0c;并利用您现有的VCL技能为未来构建下一代应用程…

python网络编程详解

最近在看《UNIX网络编程 卷1》和《FREEBSD操作系统设计与实现》这两本书&#xff0c;我重点关注了TCP协议相关的内容&#xff0c;结合自己后台开发的经验&#xff0c;写下这篇文章&#xff0c;一方面是为了帮助有需要的人&#xff0c;更重要的是方便自己整理思路&#xff0c;加…

ElasticSearch Script 操作数据最详细介绍

文章目录ElasticSearch Script基础介绍基础用法List类型数据新增、删除nested数据新增、删除根据指定条件修改数据根据指定条件修改多个字段数据-查询条件也使用脚本根据指定条件删除nested中子数据数据根据条件删除数据删除之后结果创建脚本&#xff0c;通过脚本调用根据条件查…

.net7窗口编程c#2022实战(1)-zip压缩精灵(1)

目录 创建ZIP精灵项目拖控件OpenFileDialog 类压缩与解压缩编写我们自己的代码其它参考内容创建ZIP精灵项目 VS2022中新建项目。 为窗体取一个标题名称 拖控件 左边工具栏里选择控件 拖三个按钮控件和一个listbox控件