(SSM+SE)SSO项目(1)

SSO项目笔记

一、项目结构:

在这里插入图片描述
新建一个Maven项目,取名为HandsomeAq_SSO,它有4个子module,分别是:
auth:负责权限管理
gateway:负责网关管理
resource:负责资源管理
web:负责前端管理

在HandsomeAq_SSO的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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>
    <modules>
        <module>auth</module>
        <module>resource</module>
        <module>gateway</module>
        <module>web</module>
    </modules>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.hd</groupId>
    <artifactId>HandSomeAq_SSO</artifactId>
    <version>1.0.0</version>
    <name>HandSomeAq_SSO</name>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!--Spring Cloud 依赖(定义了微服务规范)-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Hoxton.SR8</version>
            <scope>import</scope>
            <type>pom</type>
        </dependency>
        <!--Spring Cloud Alibaba依赖(基于spring微服务规范做了具体落地实现)-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.2.5.RELEASE</version>
            <scope>import</scope>
            <type>pom</type>
        </dependency>
    </dependencies>

</project>

二、auth:

首先在auth中完成SSM的相关配置,并测试数据库的连通性。参考SSM配置的文章。

在这里插入图片描述
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">
    <parent>
        <artifactId>HandSomeAq_SSO</artifactId>
        <groupId>com.hd</groupId>
        <version>1.0.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>auth</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--spring整合mybatis-plus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.3</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
        </dependency>

    </dependencies>

</project>

以上配置成功后,开始配置权限管理;

在pom文件中添加依赖:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>

启动项目做测试:
在这里插入图片描述
命令行输入默认密码;
在这里插入图片描述
生成了默认的登录界面;

输入用户名:user和生成的默认密码进行测试。

测试成功后我们进行SE的配置。

创建config包和其下的SecurityConfig.java文件,使SecurityConfig.java继承WebSecurityConfigurerAdapter 并且重写

protected void configure(HttpSecurity auth) throws Exception {

    }

用于定义认证规则和异常处理。
在这里插入图片描述
SecurityConfig:

package com.hd.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
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;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
//        关闭跨域攻击
        http
                .csrf()
                .disable();
        http
//                处理登录请求
                .formLogin();
//                .successHandler()
//                .failureHandler(null);
        http
//                处理权限,即任何请求都需要认证
                .authorizeRequests()
                .anyRequest()
                .authenticated();
    }

}

SE中有接口UserDetailsService来进行用户登录的验证,如果我们要用数据库中的信息进行登录,要实现UserDetailsService接口,并重写其中的方法:

package com.hd.service;

import com.hd.mapper.UserMapper;
import com.hd.pojo.User_Roles;
import com.hd.pojo.Users;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
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.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserDetailServiceImpl implements UserDetailsService {
    
    @Autowired
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Users users = userMapper.FindUserByUsername(username);
        if (users != null){
            List<User_Roles> user_rolesList = users.getUser_roles();
            StringBuffer buffer = new StringBuffer();
            for (User_Roles user_roles : user_rolesList) {
                String name = user_roles.getRoles().getName();
                name = "Role_"+name;
                buffer.append(name);
            }
            String Authority = new String(buffer);
            List<GrantedAuthority> grantedAuthorityList =
                    AuthorityUtils.createAuthorityList(Authority);
            User user = new User(username,users.getPassword(),grantedAuthorityList);
            return user;
        }
        throw new RuntimeException("用户不存在");
    }
}

顺便放上mapper.xml的配置文件用作参考:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hd.mapper.UserMapper">
    <resultMap id="userMap" type="Users">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="password" column="password"/>
        <collection property="user_roles" ofType="User_Roles">
            <result property="roleId" column="role_id"/>
            <collection property="roles" ofType="Roles">
                <result property="name" column="name"/>
            </collection>
        </collection>
    </resultMap>

    <select id="FindUser" resultMap="userMap">
        select u.id,u.username,u.`password`,r.`name` from
            sys_users as u left join sys_user_roles as ur on u.id = ur.user_id
                           inner join sys_roles as r on ur.role_id = r.id;
    </select>
    <select id="FindUserByUsername" resultMap="userMap">
        select u.id,u.username,u.`password`,r.`name` from
            sys_users as u left join sys_user_roles as ur on u.id = ur.user_id
                           inner join sys_roles as r on ur.role_id = r.id where u.username = #{username};
    </select>
</mapper>

<<注意>>在测试时要保证数据库中存储的密码是通过BCryptPasswordEncoder加密的,SE会将输入的密码通过BCryptPasswordEncoder后与数据库中的密码进行匹配.

启动项目进行测试。

要实现单点登录,我们需要生成一个token返回给客户,那么客户使用token就可以访问应用集群的任何一个子系统,而不需要重复的登录。

在这里插入图片描述
ticket和token是一回事,下面我们要通过用户的用户名,权限来生成token,并返回给客户:

编写两个工具类,WebUtil 用于传输用户信息。JwtUtil用来进行和token相关的操作,生成token,检验token。

JwtUtil:

package com.hd.utils;

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.Date;
import java.util.Map;

public class JwtUtil {
//    加密盐
    private static String salt = "$VGH56876531419UHF$^";
    public static String createToken(Map<String,Object> map) {
        return Jwts.builder()
//                获取用户数据
                .setClaims(map)
//                设置token生命周期
                .setExpiration(new Date(System.currentTimeMillis() + 30 * 60 * 1000))
//                设置token的开始时间
                .setIssuedAt(new Date())
                .signWith(SignatureAlgorithm.HS256, salt)
                .compact();
    }
}

WebUtil:

package com.hd.utils;

import com.fasterxml.jackson.databind.ObjectMapper;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;

public class WebUtils {
    /**将数据以json格式写到客户端
     * @param response 响应对象,负责向客户端输出数据的对象
     * @param dataMap 封装了我们要向客户端输出的数据
     * @throws IOException
     */
    public static void writeJsonToClient(
            HttpServletResponse response,
            Map<String,Object> dataMap) throws IOException {
       //1.设置响应数据的编码
        response.setCharacterEncoding("utf-8");
       //2.告诉浏览器响应数据的内容类型以及编码
        response.setContentType("application/json;charset=utf-8");
       //3.将数据转换为json格式字符串
        String jsonStr= new ObjectMapper().writeValueAsString(dataMap);
       //4.获取输出流对象将json数据写到客户端
       //4.1获取输出流对象
        PrintWriter out=response.getWriter();
       //4.2通过输出流向网络的客户端写数据
        out.println(jsonStr);
        out.flush();
    }
}

编写两个Handler,用于处理登录成功和登录失败的情况。
登录失败:

package com.hd.config.handler;

import com.hd.utils.WebUtils;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class DefaultFailureHandler implements AuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        Map<String,Object> map = new HashMap<>();
        map.put("status", 500);
        map.put("msg", "login unsuccess,please try again");
        WebUtils.writeJsonToClient(response, map);
    }
}

登录成功:

package com.hd.config.handler;

import com.hd.utils.JwtUtil;
import com.hd.utils.WebUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

public class DefaultSuccessHandler implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        User principal = (User)authentication.getPrincipal();
        Map<String,Object> UserMap = new HashMap<>();
        UserMap.put("username", principal.getUsername());
        Collection<GrantedAuthority> authorities = principal.getAuthorities();
        List AuthList = new ArrayList(authorities);
        UserMap.put("authorities", AuthList);
        String token = JwtUtil.createToken(UserMap);
        Map<String,Object> map = new HashMap<>();
        map.put("status", 200);
        map.put("msg", "login success");
        map.put("authorities", token);
        WebUtils.writeJsonToClient(response, map);
    }
}

修改SecurityConfig:

  .formLogin()
                .successHandler(new DefaultSuccessHandler())
                .failureHandler(new DefaultFailureHandler());

打开postman进行测试:
在这里插入图片描述
到这里,auth部分的配置暂时告一段落。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值