spring security 从零开始搭建
1.引入
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.3</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> <version>2.6.6</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.22</version> </dependency> </dependencies>
2.配置
package com.cj.system.config; 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.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() .formLogin() //表单登陆 1 .and() //2 .authorizeRequests() //下面的都是授权的配置 3 .antMatchers("/admin/system/index/login").anonymous()//不需授权就可以访问的 .anyRequest().authenticated(); //访问任何资源都需要身份认证 5 } }
配置完成之后登录的效果
默认用户名为user
3 修改登录名,密码为数据库用户名,密码
3.1 配置里增加
@Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Bean public PasswordEncoder passwordEncoder(){ return new MyMD5Password(); }
3.2 增加加密函数
public class MyMD5Password implements PasswordEncoder { @Override public String encode(CharSequence rawPassword) { return MD5.encrypt(rawPassword.toString()); } @Override public boolean matches(CharSequence rawPassword, String encodedPassword) { // System.out.println(rawPassword); // System.out.println(MD5.encrypt(rawPassword.toString())); // System.out.println(encodedPassword); if(MD5.encrypt(rawPassword.toString()).equals(encodedPassword)){ return true; } return false; } }
3.3 登录修改封装对象
/*start插入security*/ UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginVo.getUsername(),loginVo.getPassword()); //authenticationManager 对象 Authentication authenticate = authenticationManager.authenticate(authenticationToken); if(authenticate == null){ throw new RuntimeException("登录失败"); } MyUserDetail userDetail = (MyUserDetail) authenticate.getPrincipal();
4. 过滤器配置
4.1 配置
@Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() .formLogin() //表单登陆 1 .and() //2 .authorizeRequests() //下面的都是授权的配置 3 .antMatchers("/admin/system/index/login").anonymous() .anyRequest().authenticated(); //访问任何资源都需要身份认证 5 //添加过滤器 http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class); //添加异常处理器 http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint) .accessDeniedHandler(accessDeniedHandler); }
4.2 过滤器代码
package com.cj.system.filter; import com.cj.common.util.JwtHelper; import com.cj.model.system.SysToken; import com.cj.model.system.SysUser; import com.cj.system.custom.MyUserDetail; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; @Component public class JwtFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String token = request.getHeader("token"); if(!StringUtils.hasText(token)){ filterChain.doFilter(request,response); return; } String userId = JwtHelper.getUserId(token); String username = JwtHelper.getUsername(token); if(userId == null){ throw new RuntimeException("token非法"); } //获取信息 //TODOredis ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\\userDetail.txt")); MyUserDetail myUserDetail = null; try { myUserDetail = (MyUserDetail)objectInputStream.readObject(); } catch (ClassNotFoundException e) { e.printStackTrace(); } if(myUserDetail == null){ throw new RuntimeException("用户未登录"); } //UsernamePasswordAuthenticationToken //TODO权限 UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(myUserDetail, null, null); SecurityContextHolder.getContext().setAuthentication(authenticationToken); filterChain.doFilter(request,response); } }
4.3 效果
4.4 ps:获取的是头信息的token 使用 request.getHeader('token')
5 配置权限
5.1 在config中配置
@EnableGlobalMethodSecurity(prePostEnabled = true)
5.2 在需要验证的方法上加注解
@PreAuthorize("hasAuthority('bnt.sysRole.list')")
5.3 修改userdetail
private List<String> permissions; @Override public Collection<? extends GrantedAuthority> getAuthorities() { List<GrantedAuthority> newList = new ArrayList<>(); for(String permission:permissions){ newList.add(new SimpleGrantedAuthority(permission)); } return newList; }
5.4 修改loaduser 加上权限
List<String> permissions = sysMenuService.getUserBottonList(sysUser.getId());
5.5 修改filter
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(myUserDetail, null, myUserDetail.getAuthorities());
6 异常配置
6.1 配置
//添加异常处理器 http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint) .accessDeniedHandler(accessDeniedHandler);
6.2 权限异常
public class AccessDeniedHandlerImpl implements AccessDeniedHandler { @Override public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { Result result = new Result(403,"授权失败",null); System.out.println(accessDeniedException); WebUtil.renderString(response, JSON.toJSONString(result)); } }
6.3 授权异常
public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint { /** * 认证失败 * @param request * @param response * @param authException * @throws IOException * @throws ServletException */ @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { Result result = new Result(401,"用户认证失败请重新登录",null); WebUtil.renderString(response,JSON.toJSONString(result)); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律