通过重写configure方法添加我们自定义的认证方式。
package cn.soboys.kmall.security.config; import cn.soboys.kmall.security.service.IUserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 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.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import java.util.Set; /** * @author kenx * @version 1.0 * @date 2021/8/6 17:27 * @webSite https://www.soboys.cn/ */ @EnableWebSecurity @Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) // 控制权限注解 public class SecurityConfig extends WebSecurityConfigurerAdapter { private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint; private IUserService userService; private JwtRequestFilter jwtRequestFilter; public SecurityConfig(JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint, IUserService userService, JwtRequestFilter jwtRequestFilter) { this.jwtAuthenticationEntryPoint = jwtAuthenticationEntryPoint; this.userService = userService; this.jwtRequestFilter = jwtRequestFilter; } /** * 1)HttpSecurity支持cors。 * 2)默认会启用CRSF,此处因为没有使用thymeleaf模板(会自动注入_csrf参数), * 要先禁用csrf,否则登录时需要_csrf参数,而导致登录失败。 * 3)antMatchers:匹配 "http://www.likecs.com/" 路径,不需要权限即可访问,匹配 "/user" 及其以下所有路径, * 都需要 "USER" 权限 * 4)配置登录地址和退出地址 */ @Override protected void configure(HttpSecurity http) throws Exception { // We don\'t need CSRF for this example http.csrf().disable() // dont authenticate this particular request .authorizeRequests().antMatchers("http://www.likecs.com/", "/*.html", "/favicon.ico", "/css/**", "/js/**", "/fonts/**", "/layui/**", "/img/**", "/v3/api-docs/**", "/swagger-resources/**", "/webjars/**", "/pages/**", "/druid/**", "/statics/**", "/login", "/register").permitAll(). // all other requests need to be authenticated anyRequest().authenticated().and(). // make sure we use stateless session; session won\'t be used to // store user\'s state. //覆盖默认登录 exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement() // 基于token,所以不需要session .sessionCreationPolicy(SessionCreationPolicy.STATELESS); // Add a filter to validate the tokens with every request http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class); } @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } /** * 密码校验 * * @param auth * @throws Exception */ @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { // configure AuthenticationManager so that it knows from where to load // user for matching credentials // Use BCryptPasswordEncoder auth.userDetailsService(userService).passwordEncoder(passwordEncoder()); } /** * 密码加密验证 * * @return */ @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } } 具体应用 package cn.soboys.kmall.security.controller; import cn.hutool.core.util.StrUtil; import cn.soboys.kmall.common.exception.BusinessException; import cn.soboys.kmall.common.ret.ResponseResult; import cn.soboys.kmall.common.ret.Result; import cn.soboys.kmall.common.ret.ResultResponse; import cn.soboys.kmall.security.entity.User; import cn.soboys.kmall.security.service.IUserService; import cn.soboys.kmall.security.utils.EncryptPwdUtil; import cn.soboys.kmall.security.utils.JwtTokenUtil; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import io.swagger.annotations.*; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.DisabledException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotEmpty; import java.util.Date; import java.util.Objects; /** * @author kenx * @version 1.0 * @date 2021/8/6 12:30 * @webSite https://www.soboys.cn/ */ @RestController @ResponseResult @Validated @RequiredArgsConstructor @Api(tags = "登录接口") public class LoginController { private final IUserService userService; //认证管理,认证用户省份 private final AuthenticationManager authenticationManager; private final JwtTokenUtil jwtTokenUtil; //自己数据源 private final UserDetailsService jwtInMemoryUserDetailsService; @PostMapping("/login") @ApiOperation("用户登录") @SneakyThrows public Result login(@NotBlank @RequestParam String username, @NotBlank @RequestParam String password) { Authentication authentication= this.authenticate(username, password); String user = authentication.getName(); final String token = jwtTokenUtil.generateToken(user); //更新用户最后登录时间 User u = new User(); u.setLastLoginTime(new Date()); userService.update(u, new UpdateWrapper<User>().lambda().eq(User::getUsername, username)); return ResultResponse.success("Bearer " + token); } @PostMapping("/register") @ApiOperation("用户注册") public Result register(@NotEmpty @RequestParam String username, @NotEmpty @RequestParam String password) { User user = userService.getUserByUsername(username); if (!StrUtil.isBlankIfStr(user)) { throw new BusinessException("用户已存在"); } User u = new User(); u.setPassword(EncryptPwdUtil.encryptPassword(password)); u.setUsername(username); u.setCreateTime(new Date()); u.setModifyTime(new Date()); u.setStatus("1"); userService.save(u); return ResultResponse.success(); } private Authentication authenticate(String username, String password) throws Exception { Authentication authentication = null; try { //security 认证用户身份 authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password)); } catch (DisabledException e) { throw new BusinessException("用户不存"); } catch (BadCredentialsException e) { throw new BusinessException("用户名密码错误"); } return authentication; } } 深入了解 Spring Security 配置讲解@EnableWebSecurity 开启权限认证
@EnableGlobalMethodSecurity(prePostEnabled = true) 开启权限注解认证