springSecurity入门
准备
依赖
▼xml复制代码<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.13</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.83</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> </dependency> </dependencies>
用户实体类
▼java复制代码@Data @AllArgsConstructor @NoArgsConstructor public class User { private Long id; private String username; private String password; }
controller接口
▼Java复制代码@RestController @RequestMapping("/user") public class controller { @Autowired private LoginService loginService; @PostMapping("/login") public String login(@RequestBody User userLogin){ String token = loginService.login(userLogin); return token; } @PostMapping("/hello") @PreAuthorize("hasAuthority('user')")//这里添加访问该接口需要的角色为 ‘user’ public String hello(){ return "Hello"; } }
集成
首先实现两个接口
- UserDetailsService--springsecurity默认有认证的账号密码,我们不使用它自带的,实现这个接口重写它的方法用于获取我们真正的用户数据
▼java复制代码@Service public class UserDetailsServiceImpl implements UserDetailsService { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { if (username == null){//用户不存在的处理 throw new UsernameNotFoundException("用户不存在"); } //这里可以访问数据库获取用户信息 User user=new User(); user.setUsername("admin"); //这里的密码是admin使用BCryptPasswordEncoder加密后的结果,数据库中存储的一定是加密后的密码 user.setPassword("$2a$10$iLLMvl6E9t7qDYexmu65VOM.tVgGwp5wHh5hSG4aC7rYuRoA6I//m"); //用户权限列表,假设用户有一个user角色 List<String> list =new ArrayList<String>(Arrays.asList("user")); //封装一个loginUser对象,也是springsecurity内置对象的实现类 LoginUser loginUser = new LoginUser(user,list); return loginUser; } }
- UserDetails--spring认证需要的对象,实现这个方法加入我们自己的逻辑
▼java复制代码@Data @AllArgsConstructor @NoArgsConstructor public class LoginUser implements UserDetails { private User user;//我们自己的用户对象 private List<String> permissions;//权限列表 @JSONField(serialize = false)//一定要加,否则集成redis运行会出问题 private List<SimpleGrantedAuthority> authorities;//提取出来的字段,提高效率 //构造器--自定义 public LoginUser(User user, List<String> permissions) { this.user = user; this.permissions = permissions; } @Override //权限集合获取的方法,这个方法的逻辑也可以改写,如果User中有权限集合可以从User中获取 public Collection<? extends GrantedAuthority> getAuthorities () { if (authorities == null)//如果已经有这个集合,我们就不用再赋值一次,直接使用当前的authorities authorities = permissions.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList()); return authorities; } @Override //获取用户密码的方法 public String getPassword () { return user.getPassword(); } @Override //获取用户名 public String getUsername () { return user.getUsername(); } //以下四个方法返回值都为true即可 @Override public boolean isAccountNonExpired () { return true; } @Override public boolean isAccountNonLocked () { return true; } @Override public boolean isCredentialsNonExpired () { return true; } @Override public boolean isEnabled () { return true; } }
进行配置
▼java复制代码@Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) // 开启方法级别的安全控制 public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { @Resource private JwtFilter jwtFilter; // 过滤器链对象,用于认证和鉴权 @Bean public PasswordEncoder passwordEncoder() { // 使用 BCrypt 加密算法进行密码加密与比对 return new BCryptPasswordEncoder(); } // 注入 AuthenticationManager 对象,用于调用认证方法 @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); // 返回 AuthenticationManager 实例 } // 配置请求的权限控制 @Override protected void configure(HttpSecurity http) throws Exception { http // 关闭 CSRF 保护 .csrf().disable() // 不通过 Session 获取 SecurityContext,设置为无状态 .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() // 配置请求的授权规则 .authorizeRequests() // 对于登录接口允许匿名访问 .antMatchers("/user/login").anonymous() // 除上面外的所有请求全部需要鉴权认证 .anyRequest().authenticated(); // 在 UsernamePasswordAuthenticationFilter 前添加 JWT 过滤器 http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class); } }
过滤器
▼java复制代码@Component public class JwtFilter extends OncePerRequestFilter {//实现这个接口用于每个请求只会被处理一次 @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // 从请求头中获取 token String token = request.getHeader("token"); // 如果没有 token,继续执行后续的过滤器(例如登录流程) if (StrUtil.isBlank(token)) { filterChain.doFilter(request, response); return; } // 从 token 中提取用户信息 // 这里可以通过 JWT 工具类获取 token 中的用户信息,或从 Redis 中获取用户信息 // 为演示目的,直接实例化一个用户对象 User user = new User(); user.setUsername("admin"); // 设置用户名 user.setPassword("$2a$10$iLLMvl6E9t7qDYexmu65VOM.tVgGwp5wHh5hSG4aC7rYuRoA6I//m"); // 设置密码(已加密) // 创建一个权限列表,并添加权限 List<String> list = new ArrayList<>(); list.add("user"); // 创建 LoginUser 对象,包含用户信息和权限 LoginUser loginUser = new LoginUser(user, list); // 登录成功后,使用 UsernamePasswordAuthenticationToken 存储用户信息和权限信息 UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities()); // 将用户信息存入 SecurityContext,后续可以从这里取出用户信息 SecurityContextHolder.getContext().setAuthentication(authenticationToken); // 继续执行后续的过滤器链 filterChain.doFilter(request, response); } }
在LoginService实现类中进行认证
▼java复制代码@Service public class LoginService { @Resource private AuthenticationManager manager; // 注入 AuthenticationManager,用于用户认证 public String login(User user) { // 创建 UsernamePasswordAuthenticationToken,用于认证 UsernamePasswordAuthenticationToken userAuthentication = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()); // 调用 AuthenticationManager 的方法进行用户认证 Authentication authenticate = manager.authenticate(userAuthentication); // 如果认证成功(authenticate 不为空),进入生成 token 的逻辑 if (!Objects.isNull(authenticate)) { // 获取 LoginUser 对象 LoginUser loginUser = (LoginUser) authenticate.getPrincipal(); // 获取真正的 User 对象 User u = loginUser.getUser(); // 生成 token String token = JWT .create() .setPayload("userLoginId", u.getId()) // 设置用户 ID 为负载 .setIssuedAt(new Date()) // 设置 token 的发放时间 .setExpiresAt(new Date(System.currentTimeMillis() + DateUnit.WEEK.getMillis())) // 设置过期时间为一周 .setSigner("HMD5", "salt".getBytes(StandardCharsets.UTF_8)) // 设置加密算法和盐值 .sign(); // 生成并签名 token // 返回生成的 token return token; } // 如果认证失败,抛出异常 throw new RuntimeException("用户名或密码错误"); } }
测试
## 携带刚刚生成的token去访问需要权限的接口

评论
问答助学
相关内容
0个评论
全部评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
内容推荐
day5 今天学了四个小时,学了HttpServlerRequest和MySQL
11
day3学完HTTP协议复习了一些Javase的内容明天开始背面经
15
day2今天看完了Servlet,明天看HTTP。今天敲了敲坦克大战,想半天也实现不了,非得看课程。头疼。代码要还是敲了记忆才深刻,尤其是自己单独想通逻辑,然后不看视频就单独敲出来才能算初步学会,每天坚持,慢慢来吧
12
day1打卡今天主要看了韩顺平老师javaweb课程的Tomcat和Servlet的一小部分,前面的前端部分以前学过,就大概看了一下笔记复习了一下。今天感觉对tomcat和Servlet的理解有很大的提升,韩老师的课程很适合我。明天继续加油,明天应该看完Servlet差不多,这里自己第一次学就没学明白,明天就学明白Servlet就好,然后再练习一下SQL语句。
15
✅ 今天做了:学习AI零代码应用生成平台之对话历史模块,完成对话记忆⏰ 明天计划:📚 今日感悟:
0
