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>
< 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> < dependency> < groupId> com.github.xiaoymin</ groupId> < artifactId> knife4j-spring-boot-starter</ artifactId> < version> 2.0.9</ version> </ dependency> < dependency> < groupId> com.auth0</ groupId> < artifactId> java-jwt</ artifactId> < version> 3.10.3</ version> </ dependency> < dependency> < groupId> org.springframework.boot</ groupId> < artifactId> spring-boot-starter-data-redis</ artifactId> </ dependency> < dependency> < groupId> com.baomidou</ groupId> < artifactId> mybatis-plus-boot-starter</ artifactId> < version> 3.5.1</ version> </ dependency>
< 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 配置系统文件
spring : redis : host : 127.0.0.1port : 6379 datasource : driver-class-name : com.mysql.cj.jdbc.Driverurl : jdbc: mysql: //localhost: 3306/text012? userSSL=false;serverTimezone=Asia/Shanghaiusername : rootpassword : 1234 mvc : pathmatch : matching-strategy : ant_path_matcher
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 { @Autowired private MsUserServiceImp msUserServiceImp; @Override public UserDetails loadUserByUsername ( String username) throws UsernameNotFoundException { LambdaQueryWrapper < MsUser > qw= new LambdaQueryWrapper < > ( ) ; qw. eq ( MsUser :: getUsername , username) ; MsUser user = msUserServiceImp. getOne ( qw) ; LoginUser loginUser = new LoginUser ( ) ; loginUser. setMsUser ( user) ; return loginUser; }
}
05 重写UserDetails接口
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties ( ignoreUnknown = true )
public class LoginUser implements UserDetails { private MsUser msUser; @Override public Collection < ? extends GrantedAuthority > getAuthorities ( ) { return null ; } @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 { @Autowired private JWTFilter jwtFilter; @Bean public PasswordEncoder passwordEncoder ( ) { return new BCryptPasswordEncoder ( ) ; } @Override protected void configure ( HttpSecurity http) throws Exception { http. addFilterBefore ( jwtFilter, UsernamePasswordAuthenticationFilter . class ) ; http. csrf ( ) . disable ( ) . sessionManagement ( ) . sessionCreationPolicy ( SessionCreationPolicy . STATELESS ) . and ( ) . authorizeRequests ( ) . antMatchers ( "/msUser/login" ) . anonymous ( ) . anyRequest ( ) . authenticated ( ) ; } @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 { @Autowired private AuthenticationManager authenticationManager; @Autowired private RedisUtil redisUtil; @Override public AjaxResult login ( MsUser user) { 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 ( ) ; 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) ; }
}