redis+springsecurity+mybtais-plus+JWT 今天药忘吃喽~ 2024-02-05 12:47 44阅读 0赞 ## 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); } }
还没有评论,来说两句吧...