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.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
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);
}
}