实战2 SpringBoot Security用户认证

目录

1、Spring Security介绍

2、Spring Security认证步骤 

3、Spring Security认证实现 

3.1 添加Spring Security依赖

3.2 自定义UserDetails类 

3.3 编写UserService接口

3.4 编写UserService接口实现类

3.5 自定义UserDetailsService类

3.6 编写自定义认证成功处理器

3.7 编写自定义认证失败处理器

3.8 编写用户无权限访问处理器

3.9 编写匿名用户访问资源处理器

3.10 编写Spring Security配置类


1、Spring Security介绍

2、Spring Security认证步骤 

3、Spring Security认证实现 

3.1 添加Spring Security依赖

3.2 自定义UserDetails类 

@Getter
@Setter
@TableName("sys_user")
@ApiModel(value = "User对象", description = "")
public class User implements Serializable, UserDetails {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty("用户编号")
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    @ApiModelProperty("登录名称(用户名)")
    private String username;

    @ApiModelProperty("登录密码")
    private String password;

    @ApiModelProperty("帐户是否过期(1-未过期,0-已过期)")
    private boolean isAccountNonExpired =true;

    @ApiModelProperty("帐户是否被锁定(1-未过期,0-已过期)")
    private boolean isAccountNonLocked=true;

    @ApiModelProperty("密码是否过期(1-未过期,0-已过期)")
    private boolean isCredentialsNonExpired=true;

    @ApiModelProperty("帐户是否可用(1-可用,0-禁用)")
    private boolean isEnabled =true;
    @ApiModelProperty("真实姓名")
    private String realName;

    @ApiModelProperty("昵称")
    private String nickName;

    @ApiModelProperty("所属部门ID")
    private Long departmentId;

    @ApiModelProperty("所属部门名称")
    private String departmentName;

    @ApiModelProperty("性别(0-男,1-女)")
    private Integer gender;

    @ApiModelProperty("电话")
    private String phone;

    @ApiModelProperty("邮箱")
    private String email;

    @ApiModelProperty("用户头像")
    private String avatar;

    @ApiModelProperty("是否是管理员(1-管理员)")
    private Integer isAdmin;

    @ApiModelProperty("创建时间")
    private Date createTime;

    @ApiModelProperty("修改时间")
    private Date updateTime;

    @ApiModelProperty("是否删除(0-未删除,1-已删除)")
    private Integer isDelete;
    /**     * 权限列表     */   
    @TableField(exist = false)
    Collection<? extends GrantedAuthority> authorities;

    @TableField(exist = false)
    private List<Permission> permissionList;
}

3.3 编写UserService接口

在com.cizhu.service.UserService接口编写根据用户名查询用户信息的方法

public interface IUserService extends IService<User> {
    /**
     * 根据用户名查询用户信息
     * @param userName
     * @return
     */
    User findUserByUserName(String userName);
}

3.4 编写UserService接口实现类

@Service
@Transactional
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    /**
     * 根据用户名查询用户信息
     * @param userName
     * @return
     */
    @Override
    public User findUserByUserName(String userName) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username",userName);
        // 返回查询记录
        return baseMapper.selectOne(queryWrapper);
    }
}

3.5 自定义UserDetailsService类

@Component
public class CustomerUserDetailsService implements UserDetailsService {
    @Resource
    private IUserService userService;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //调用根据用户名查询用户信息的方法
        User user = userService.findUserByUserName(username);
        if (user ==null){
            throw new UsernameNotFoundException("用户名或密码错误");
        }
        return user;
    }
}

3.6 编写自定义认证成功处理器

在com.cizhu.config.security.handler包下创建LoginSuccessHandler登录认证成功处理器

@Component
public class LoginSuccessHandler implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        //设置响应编码格式
        response.setContentType("applicaiton/json;charset=utf-8");
        //换取当前登录用户信息
        User user = (User)authentication.getPrincipal();
        //将对象转换成JSON格式,并消除循环引用
        String result = JSON.toJSONString(user, SerializerFeature.DisableCircularReferenceDetect);
        //获取输出流
        ServletOutputStream outputStream = response.getOutputStream();
        outputStream.write(result.getBytes(StandardCharsets.UTF_8));
        outputStream.flush();
        outputStream.close();
    }
}

3.7 编写自定义认证失败处理器

@Component
public class LoginFailureHandler implements AuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        //设置响应编码格式
        response.setContentType("applicaiton/json;charset=utf-8");
        //获取输出流
        ServletOutputStream outputStream = response.getOutputStream();
        //定义变量,保存异常信息
        String message = null;
        //判断异常类型
        if(exception instanceof AccountExpiredException){
            message="账户过期,登录失败!";
        }else if(exception instanceof BadCredentialsException){
            message="用户名和密码错误,登录失败!";
        }else if (exception instanceof CredentialsExpiredException){
            message="密码过期,登录失败!";
        } else if (exception instanceof DisabledException) {
            message="账户被禁用,登录失败!";
        } else if (exception instanceof LockedException) {
            message="账户被锁,登录失败!";
        } else if (exception instanceof InternalAuthenticationServiceException) {
            message="账户不存在,登录失败!";
        }else {
            message="登录失败!";
        }
        //将结果转换成JSON格式
        String result = JSON.toJSONString(Result.error().code(500).message(message));
        //将结果保存输出中写出
        outputStream.write(result.getBytes(StandardCharsets.UTF_8));
        outputStream.flush();
        outputStream.close();
    }

3.8 编写用户无权限访问处理器

在com.cizhu.config.security.handler包下创建CustomerAccessDeniedHandler认证用户访问无权限资源时处理器类。

package com.cizhu.config.security.service.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.cizhu.utils.Result;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * 用户无权限访问资源处理器
 */
@Component
public class CustomerAccessDeniedHandler implements AccessDeniedHandler {


    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        //设置客户端的响应的内容类型
        response.setContentType("application/json;charset=UTF-8");
//获取输出流
        ServletOutputStream outputStream = response.getOutputStream();
//消除循环引用
        String result = JSON.toJSONString(Result.error().code(700).message(
                "无权限访问, 请联系管理员!"), SerializerFeature.DisableCircularReferenceDetect);
        outputStream.write(result.getBytes(StandardCharsets.UTF_8));
        outputStream.flush();
        outputStream.close();
    }
}

3.9 编写匿名用户访问资源处理器

在com.cizhu.config.security.handler包下创建AnonymousAuthenticationHandler匿名用户访问资源处理器类

package com.cizhu.config.security.service.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.cizhu.utils.Result;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * 匿名用户访问资源处理器
 */
@Component
public class AnonymousAuthenticationHandler implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse
            response, AuthenticationException authException) throws IOException,
            ServletException {
//设置客户端的响应的内容类型
        response.setContentType("application/json;charset=UTF-");
//获取输出流
        ServletOutputStream outputStream = response.getOutputStream();
//消除循环引用
        String result = JSON.toJSONString(Result.error().code(600).message(
                "匿名用户无权限访问!"), SerializerFeature.DisableCircularReferenceDetect);
        outputStream.write(result.getBytes(StandardCharsets.UTF_8));
        outputStream.flush();
        outputStream.close();
    }
}

3.10 编写Spring Security配置类

在com.cizhu.config.security包下创建SpringSecurityConfig配置类

package com.cizhu.config.security;

import com.cizhu.config.security.filter.CheckTokenFilter;
import com.cizhu.config.security.handler.AnonymousAuthenticationHandler;
import com.cizhu.config.security.handler.CustomerAccessDeniedHandler;
import com.cizhu.config.security.handler.LoginFailureHandler;
import com.cizhu.config.security.handler.LoginSuccessHandler;
import com.cizhu.config.security.service.CustomerUserDetailsService;
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.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.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.Resource;

@Configuration
@EnableWebSecurity
//开启权限注解控制
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private CustomerUserDetailsService customerUserDetailsService;
    @Resource
    private LoginSuccessHandler loginSuccessHandler;
    @Resource
    private LoginFailureHandler loginFailureHandler;
    @Resource
    private AnonymousAuthenticationHandler anonymousAuthenticationHandler;
    @Resource
    private CustomerAccessDeniedHandler customerAccessDeniedHandler;
    @Resource
    private CheckTokenFilter checkTokenFilter;
    /**
     *
     * .. 测试登录认证接口
     * 注入加密处理类
     *
     * @return
     */
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        //登录前进行过滤
        http.addFilterBefore(checkTokenFilter,
                UsernamePasswordAuthenticationFilter.class);
        http.formLogin()
                .loginProcessingUrl("/api/user/login")
// 设置登录验证成功或失败后的的跳转地址
                .successHandler(loginSuccessHandler).failureHandler(loginFailureHandler)
// 禁用csrf防御机制
                .and().csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers("/api/user/login").permitAll()
                .anyRequest().authenticated()
                .and()
                .exceptionHandling()
                .authenticationEntryPoint(anonymousAuthenticationHandler)
                .accessDeniedHandler(customerAccessDeniedHandler)
                .and().cors();//开启跨域配置
    }

    /**
     * 配置认证处理器
     *
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customerUserDetailsService).passwordEncoder(
                passwordEncoder());
    }
}

  • 27
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Security OAuth2是一个基于Spring Security的扩展,用于实现OAuth2协议中的认证和授权功能。它提供了多种认证模式,其中包括client模式。在client模式下,客户端直接通过自己的凭证向授权服务器进行认证,获取访问令牌后可以直接访问受保护的资源。 实现单点登录功能可以使用Spring Security OAuth2来实现。单点登录是指用户只需要登录一次,就可以访问多个相互信任的应用系统。在Spring Security OAuth2中,可以通过配置多个客户端来实现单点登录。每个客户端都有自己的clientId和clientSecret,当用户登录成功后,会生成一个访问令牌,并将该令牌保存在认证服务器中。其他应用系统可以通过验证访问令牌的方式来实现单点登录。 具体的实现步骤可以参考以下链接: - \[Spring Cloud Security:Oauth2实现单点登录\](https://www.macrozheng.com/cloud/oauth2_sso.html#oauth2-client%E6%B7%BB%E5%8A%A0%E6%9D%83%E9%99%90%E6%A0%A1%E9%AA%8C) \[1\] - \[简述 Spring Security OAuth2的认证client模式\](https://www.kancloud.cn/zhangchio/springboot/663138) \[2\] - \[spring-security-oauth2是对OAuth2协议中授权类型的具体实现,也是我们实现单点登录功能实际用到的代码\](https://blog.csdn.net/pxg943055021/article/details/124752669) \[3\] 通过参考以上链接,你可以了解如何使用Spring Security OAuth2来实现单点登录功能。 #### 引用[.reference_title] - *1* *2* *3* [Spring Cloud Security:Oauth2 单点登录](https://blog.csdn.net/qq_19636353/article/details/127025830)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值