SpringBoot框架:集成Security完成认证鉴权

一、导入依赖包

  1、导入security相关包:

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>

二、基础部署

  1、HelloController.java:

  在Controller层里编写一些简单的接口,用于测试认证和鉴权。

package com.example.demo.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @RequestMapping("/hello") public String hello(){ return "hello"; } @RequestMapping("/404") public String hello404(){ return "404"; } @RequestMapping("/403") public String hello403(){ return "403"; } @RequestMapping("/500") public String hello500(){ return "500"; } }

  2、UserPo.java:

  用户实体类,用来存储用户信息和用户所拥有的的角色权限。

package com.example.demo.po; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.List; public class UserPo implements Serializable, UserDetails { /** 主键id */ private Long id; /** 用户名 */ private String userName; /** 密码 */ private String password; /** 昵称 */ private String nickName; /** 用户是否可用 */ private boolean enabled; /** 角色集合 */ private List<RolePo> roles; /** 注册时间 */ private String regTime; public Long getId() { return id; } public void setId(Long id) { this.id = id; } @Override public String getUsername() { return userName; } /** * 获取角色权限 * @return */ @Override public Collection<? extends GrantedAuthority> getAuthorities() { List<GrantedAuthority> authorities = new ArrayList<>(); for (RolePo role : roles) { authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getName())); } return authorities; } /** * 账户未使用 * @return */ @Override public boolean isAccountNonExpired() { return true; } /** * 账户未锁定 * @return */ @Override public boolean isAccountNonLocked() { return true; } /** * 权限未启用 * @return */ @Override public boolean isCredentialsNonExpired() { return true; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getNickName() { return nickName; } public void setNickName(String nickName) { this.nickName = nickName; } @Override public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public boolean isEnabled() { return enabled; } public void setEnabled(boolean enabled) { this.enabled = enabled; } public List<RolePo> getRoles() { return roles; } public void setRoles(List<RolePo> roles) { this.roles = roles; } public String getRegTime() { return regTime; } public void setRegTime(String regTime) { this.regTime = regTime; } }

  该类实现UserDetails接口,这个是Sercurity里自带的类,而且实现其中的各个方法,像getAuthorities这个方法是比较重要的,要将自己从数据库里读出的用户角色进行处理,带上角色前缀“ROLE_”,用于鉴权的hasRole方法使用。

  类似于isAccountNonExpired、isAccountNonLocked、isCredentialsNonExpired这些方法,要返回true,否则在登录时会提示用户被锁住等信息。

  3、UserService.java:

  UserService直接继承UserDetailsService类,在实现类里对该类的方法进行重写。

package com.example.demo.service; import org.springframework.security.core.userdetails.UserDetailsService; public interface UserService extends UserDetailsService { }

  4、UserServiceImpl.java:

  UserServiceImpl实现UserDetailsService中的loadUserByUsername

package com.example.demo.service.impl; import com.example.demo.mapper.RoleMapper; import com.example.demo.mapper.UserMapper; import com.example.demo.po.RolePo; import com.example.demo.po.UserPo; import com.example.demo.service.UserService; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import java.util.List; @Service public class UserServiceImpl implements UserService { @Autowired UserMapper userMapper; @Autowired RoleMapper roleMapper; /** * 根据用户名获取用户信息 * @param s * @return * @throws UsernameNotFoundException */ @Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { //参数为空,返回空 if(StringUtils.isEmpty(s)){ return null; } //参数不为空,返回获取到的用户信息 UserPo userPo = userMapper.getUserByUserName(s); //填充用户角色信息 List<RolePo> rolePos = roleMapper.getRolesByUserId(userPo.getId()); userPo.setRoles(rolePos); userPo.getAuthorities(); return userPo; } }

  根据用户名获取用户信息,并通过用户与角色的关联关系取得角色信息,使用getAuthorities方法将角色配给用户。

  5、WebSecurityConfig.java:

  该类继承WebSecurityConfigurerAdapter适配器,添加加密工具以及配置相关接口的开放和拦截。

package com.example.demo.config; import com.example.demo.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired UserService userService; /** * 获取加密工具 * @return */ @Bean public PasswordEncoder getPasswordEncoder(){ return new BCryptPasswordEncoder(); } @Override public void configure(AuthenticationManagerBuilder auth) throws Exception{ auth.userDetailsService(userService) .passwordEncoder(getPasswordEncoder()); } /** * 处理接口的开放和拦截 * @param http * @throws Exception */ @Override protected void configure(HttpSecurity http) throws Exception{ http.authorizeRequests() //开放拦截 .antMatchers("/500").permitAll() .antMatchers("/403").permitAll() .antMatchers("/404").permitAll() .antMatchers("/hello").hasRole("admin") //其他任何请求都要进行身份认证 .anyRequest() .authenticated() .and() //表单提交数据 .formLogin() //配置登录接口 .loginProcessingUrl("/login") .and() //关闭跨站请求伪造保护 .csrf().disable(); } }

  按照上面的配置,现在404、403、500接口都是开放的,认证之后即可访问,不做权限拦截。

  但是hello这个接口需要登录认证之后,再进行权限判断,即角色字段要与hasRole中的一致。


__EOF__

本文作者我命倾尘
本文链接https://www.cnblogs.com/guobin-/p/14207032.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   我命倾尘  阅读(638)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
点击右上角即可分享
微信分享提示