redis+springsecurity+mybtais-plus+JWT

redis+springsecurity+mybtais-plus+JWT

01 引入依赖

       
		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
<!--lombok依赖-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--    使用knife4j依赖 -->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>2.0.9</version>
        </dependency>

        <!-- jwt依赖-->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.10.3</version>
        </dependency>
        <!--redis依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--mybatisplus依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>
<!--        spring-security依赖-->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

02 配置系统文件

#配置redis的端口和mybatis—plus的数据源,swagger的配置信息
spring:
  redis:
    host: 127.0.0.1
    port: 6379
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/text012?userSSL=false;serverTimezone=Asia/Shanghai
    username: root
    password: 1234
  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher
#开启驼峰转化,mapper的xml文件夹扫描      
mybatis-plus:
  config-locations: classpath:mapper/*.xml
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

03 配置启动类

@SpringBootApplication
@MapperScan("com.example.demo.mapper")
public class DemoApplication {
    
    

    public static void main(String[] args) {
    
    
        SpringApplication.run(DemoApplication.class, args);
    }
}

04 重写UserDetailsService接口

@Service
public class UserDetailsServiceImpl implements UserDetailsService {
    
    
 //这是mybatis-plus所实现的数据操作层,不使用mybatis-plus就不写
    @Autowired
    private MsUserServiceImp msUserServiceImp;

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

        //使用mybatis-plus,获取到账号密码数据
        LambdaQueryWrapper<MsUser> qw=new LambdaQueryWrapper<>();
        qw.eq(MsUser::getUsername,username);
        MsUser user = msUserServiceImp.getOne(qw);

        //下一步就是重写UserDetails接口
        LoginUser loginUser = new LoginUser();
        loginUser.setMsUser(user);

        return loginUser;
    }
}

05 重写UserDetails接口

//前三个是lombok的模块化配置,第四个是redis的序列化配置
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class LoginUser implements UserDetails {
    
    

    //首先要写一个与数据库内表对应的实体类
    private MsUser msUser;
    //重写审核方法
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
    
    
        return null;
    }

    //返回实体类MsUser中Password(密码)和Username(账号名对应的属性),将判断方法的返回值都改为true
    @Override
    public String getPassword() {
    
    
        return msUser.getPassword();
    }

    @Override
    public String getUsername() {
    
    
        return msUser.getUsername();
    }

    @Override
    public boolean isAccountNonExpired() {
    
    
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
    
    
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
    
    
        return true;
    }

    @Override
    public boolean isEnabled() {
    
    
        return true;
    }
}

四个关键点

1.UserDetails接口的实现类需要一个实体类属性(类似MsUser)
2.getPassword和getUsername方法需要返回实体类(MsUser)中代表账号名和密码的属性的值
3.五个判断账号使用的情况的方法需要返回true,不然无法正常使用

06 重写springSecurity的配置类

  • 实现WebSecurityConfigurerAdapter接口
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    

    //需要自定义JWT过滤器
    @Autowired
    private JWTFilter jwtFilter;

    //设置密码的加密方式
    @Bean
    public PasswordEncoder passwordEncoder(){
    
    
        return new BCryptPasswordEncoder();
    }

    //关闭原有的登录接口和页面,后端只完成接口即可,让前端去画登录界面
    @Override
    protected void configure(HttpSecurity http) throws Exception {
    
    

        http// 将自己定义的过滤器加到UsernamePasswordAuthenticationFilter之前
                .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
        http
                //关闭csrf
                .csrf().disable()
                //不通过Session获取SecurityContext
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                // 对于登录接口 允许匿名访问
                .antMatchers("/msUser/login").anonymous()
                // 除上面外的所有请求全部需要鉴权认证
                .anyRequest().authenticated();
    }


    //顺便设置JWT的token验证方式,这里我没重写,使用springsecurity原有的实现方式
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
    
    
        return super.authenticationManagerBean();
    }
}

五个关键点

1.自定义JWT过滤器
2.设置密码的加密方式
3.addFilterBefore,把自定义的JWT的过滤器加到UsernamePasswordAuthenticationFilter过滤器前
4.关闭csrf(原有的登录界面和接口)
5.设置JWT的token验证方式

07 写登录实现类

  • 我这里采用mybatis-plus实现从数据库获取数据,其他方式也可
@Service
public class MsUserServiceImp extends ServiceImpl<MsUserMapper, MsUser>
    implements IMsUserService {
    
    
    //注入AuthenticationManager对象
    @Autowired
    private AuthenticationManager authenticationManager;
	//写一个用于使用Redis工具类
    @Autowired
    private RedisUtil redisUtil;

	//AjaxResult是我用于设置返回的工具类,不重要
    @Override
    public AjaxResult login(MsUser user) {
    
    
        //token的验证
        UsernamePasswordAuthenticationToken token=new UsernamePasswordAuthenticationToken(user.getUsername(),user.getPassword());
        Authentication authentication=authenticationManager.authenticate(token);
        if (Objects.isNull(authentication)){
    
    
            throw new RuntimeException("认证失败");
        }
        //合格说明通过
        LoginUser loginUser=(LoginUser) authentication.getPrincipal();
        //使用JWT创建token,这里我封装了一个JWT的工具类
        String jwt= JWTUtil.createToken(loginUser.getMsUser());

        try {
    
    
            redisUtil.setCacheObject("user:"+loginUser.getMsUser().getUserId(),loginUser);
        }catch (Exception e){
    
    
            e.printStackTrace();
        }


        return AjaxResult.success("登录成功",jwt);
    }
}

三个关键点

1.调用springsecurity的工具类验证前端参数
2.使用JWT工具类生成token
3.redis的数据储存

08 测试

@RestController
@RequestMapping("/msUser")
public class MsUserController {
    
    
    @Autowired
    private MsUserServiceImp userServiceImp;

    @PostMapping("/login")
    public AjaxResult<String> login(MsUser user) {
    
    
        System.out.println(user);
        return userServiceImp.login(user);
    }
}

猜你喜欢

转载自blog.csdn.net/2302_77182979/article/details/134839039