IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Springboot引入springSecurity -> 正文阅读

[Java知识库]Springboot引入springSecurity

1:添加Spring Security依赖

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

2:添加完以后启动项目

2.1:此时控制台出现变化,出现一行密码

2.2:再次访问项目地址http://localhost:8081/

此时会出现权限框架的登录页

默认的用户名是:user,密码:控制台上出现的密码

输入以后才能访问接口信息

3:编写SpringSecurity核心配置类,实现自定义登录

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig  extends WebSecurityConfigurerAdapter {

    @Resource
    private UserDetailsServiceImpl UserDetailsService;

    @Resource
    private JwtAuthenticationEntryPoint authenticationEntryPoint;

    @Resource
    private JwtAccessDeniedHandler accessDeniedHandler;

    @Resource
    private PasswordEncoder passwordEncoder;

    @Resource
    private JwtAuthenticationFilter authenticationFilter;


    /**
     * 配置白名单
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().mvcMatchers(SpringSecurityConstant.NONE_SECURITY_URL_PATTERNS);
    }

    /**
     * Security的核心配置
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 1.使用jwt,关闭csrf
        http.csrf().disable();
        // 2.基于token认证,关闭session
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        // 3.配置白名单 除白名单以外的都进行认证
        http.authorizeRequests().anyRequest().authenticated();
        // 4.禁用缓存
        http.headers().cacheControl();
        // 5.添加jwt登录授权的过滤器
        http.addFilterBefore(authenticationFilter, UsernamePasswordAuthenticationFilter.class);
        // 6.添加未授权和未登录的返回结果
        http.exceptionHandling().accessDeniedHandler(accessDeniedHandler)
                .authenticationEntryPoint(authenticationEntryPoint);
    }

    /**
     * 登录认证
     * 自定义登录逻辑的配置
     * 也就是配置的security进行认证
     * */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(UserDetailsService).passwordEncoder(passwordEncoder);
    }


}

3.1:token认证过滤器,在接口访问前进行过滤

public class JwtAuthenticationFilter extends OncePerRequestFilter {
    @Resource
    private TokenUtil tokenUtil;

    @Resource
    private UserDetailsService userDetailsService;

    @Value("${jwt.tokenHeader}")
    private String tokenHeader;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        //1:获取请求头中的token
        String token = request.getHeader(tokenHeader);
        //2:判断token是否存在
        if(!StrUtil.isBlank(token)){
            //根据token获取用户名
            String userName = tokenUtil.getUserNameFromToken(token);
            //3:token存在但是security里面没有登录信息,代表有token但是没登录
            if(null == SecurityContextHolder.getContext().getAuthentication()){
                //没有登录信息,直接登录
                UserDetails userDetails = userDetailsService.loadUserByUsername(userName);
                //判断token是否有效,token没有过期,并且和userdetail中的username一样,那么就将security中的登录信息进行刷新
                if(tokenUtil.isExpiration(token) && userName.equals(userDetails.getUsername())){
                    //刷新security中的用户信息
                    UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                    authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    SecurityContextHolder.getContext().setAuthentication(authenticationToken);
                }
            }
        }
        chain.doFilter(request, response);
    }
}

3.2:重写WebSecurityConfigurerAdapter下的userDetailsService 实现自定义的登录

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Resource
    private SysUserService sysUserService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SysUser sysUser = sysUserService.findByUserName(username);
        if(null != sysUser){
            return sysUser;
        }
        throw new RuntimeException("用户名或密码错误");
    }
}

3.3:用户访问无权限资源时候的异常

@Configuration
public class JwtAuthenticationEntryPoint  implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json");
        response.setStatus(401);
        PrintWriter printWriter = response.getWriter();
        printWriter.write(new ObjectMapper().writeValueAsString(Result.fail("您尚未登录或登录信息已过期,请重新登录!")));
        printWriter.flush();
        printWriter.close();
    }
}

3.4:当用户权限不足情况下访问资源的返回异常

@Configuration
public class JwtAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json");
        response.setStatus(403);
        PrintWriter printWriter = response.getWriter();
        printWriter.write(new ObjectMapper().writeValueAsString(Result.fail("权限不足,请联系管理员!")));
        printWriter.flush();
        printWriter.close();
    }
}

3.5:白名单配置类

public class SpringSecurityConstant {
	
	/**
     * 放开权限校验的接口
     */
    public static final String[] NONE_SECURITY_URL_PATTERNS = {
    		//前端的
            "/favicon.ico",
            //swagger相关的
            "/doc.html",
            "/webjars/**",
            "/swagger-resources/**",
            "/v2/api-docs",
            "/v2/api-docs-ext",
            "/configuration/ui",
            "/configuration/security",
    		//后端的
            "/login",
            "/sysLogin"
            
    };

}

3.6:编写Bean配置

@Configuration
public class BeanConfig {

    @Bean
    public JwtAuthenticationFilter authenticationFilter() {
        return new JwtAuthenticationFilter();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

4:编写跨域配置类,前后端分离项目

public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry
                //允许访问路径
                .addMapping("/**")
                //配置请求来源
                .allowedOrigins("http://localhost:8081")
                //配置允许访问的方法
                .allowedMethods("GET","POST","PUT","DELETE","OPTION")
                //配置最大响应时间 6秒
                .maxAge(3600)
                //是否允许携带参数
                .allowCredentials(true)
                //允许请求头
                .allowedHeaders();
    }
}

5:进行登录编写,具体实现逻辑

5.1:编写用户登录的实体类,实现UserDetails

@Data
public class SysUser implements UserDetails {

    private Long id;
    private String userName;
    private String passWord;
    private Integer age;
    private Character sex;
    private String avatar;
    private String address;
    private String openId;
    private Boolean status;
    private Boolean admin;
    private String phoneNumber;

    /**
     * 权限数据
     * */
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }

    @Override
    public String getPassword() {
        return null;
    }

    /**
     * 获取用户名
     * */
    @Override
    public String getUsername() {
        return null;
    }

    /**
     * 账号是否过期
     * */
    @Override
    public boolean isAccountNonExpired() {
        return false;
    }

    /**
     * 账号是否被锁定
     * */
    @Override
    public boolean isAccountNonLocked() {
        return false;
    }

    /**
     * 凭证是否过期
     * */
    @Override
    public boolean isCredentialsNonExpired() {
        return false;
    }

    /**
     * 是否被禁用
     * */
    @Override
    public boolean isEnabled() {
        //直接返回数据库中查出的用户状态
        return status;
    }
}

?5.2:定义Controller类,添加登录方法

@RestController
@Api("用户信息登录控制器")
public class LoginConyroller {

	@Autowired
	private UserService userService;
	
	@Autowired
	private RedisUtil redisUtil;

    @PostMapping("/sysLogin")
	@ApiOperation(value = "系统用户登录", httpMethod = "POST")
	public Result sysLogin(@RequestBody @Valid SysLoginVo sysLoginVo) {
		return userService.sysLogin(sysLoginVo);
	}

	
	@GetMapping("/logOut")
	@ApiOperation(value = "退出登录", httpMethod = "GET")
	public Result logOut(HttpServletRequest request, HttpServletResponse 
        response,Principal principal ) {
		//清除spring security用户认证信息
		Authentication auth = SecurityContextHolder.getContext().getAuthentication();
		//清除redis中的token信息
		redisUtil.delKey(principal.getName());
		if(null != auth) {
			new SecurityContextLogoutHandler().logout(request, response, auth);
		}
		return new Result(MessageConstant.SUCCESS_CODE, MessageConstant.LOGOUT_SUCCESS);
	}			

}

?5.3:定义userService接口

public interface UserService {	     
   /**
     * 登录
     * @param loginVo
     * @return
     */
	
	Result sysLogin(SysLoginVo sysLoginVo);
}

?5.5:实现userService接口

@Service
public class SysUserServiceImpl implements SysUserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private UserDetailsService userDetailsService;

    @Resource
    private PasswordEncoder passwordEncoder;

    @Resource
    private TokenUtil tokenUtil;

    @Value("${jwt.tokenHeader}")
    private String tokenHeader;

    @Override
    public Result login(LoginVo loginVo) {
        UserDetails userDetails = userDetailsService.loadUserByUsername(loginVo.getUserName());
        //如果为空,则账号不存在,判断传过来的密码和userDetails里面的密码是否匹配
        if(null == userDetails || !passwordEncoder.matches(loginVo.getPassWord(), userDetails.getPassword())){
            return Result.fail("账号或密码错误,请重新输入");
        }
        //判断账号是否禁用
        if(!userDetails.isEnabled()){
            return Result.fail("该账号已禁用,请联系管理员");
        }
        //如果这些都验证通过,则需要在spring security中存入当前用户登录信息
        //第一个参数是登录信息,密码,权限信息
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                new UsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities());
        //将权限信息设置进去
        SecurityContextHolder.getContext()
                .setAuthentication(usernamePasswordAuthenticationToken);
        //根据登录信息,借助JWT获取token
        String token = tokenUtil.generateToken(userDetails);
        Map<String,String> map = new HashMap<>(2);
        map.put("tokenHeader",tokenHeader);
        map.put("token",token);
        return Result.success("登录成功",map);
    }

    /**
     * 根据用户名获取用户对象
     * */
    @Override
    public SysUser findByUserName(String userName) {
        return userMapper.findByUserName(userName);
    }
}

至此,springboot集成springsecurity的配置demo完成,具体里面的权限配置还需要自己implements UserDetails类中再进行细化

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-10-17 12:18:51  更:2022-10-17 12:20:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/30 14:08:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码