zoukankan      html  css  js  c++  java
  • Spring Security自定义用户认证

    具体代码地址 https://gitee.com/chuzhuyong/HandleSafer

    自定义用户认证

      通过自定义WebSecurityConfigurerAdapter类型的Bean组件,并重写configure(Authentication ManagerBuilder auth)方法,

    可以实现自定义用户认证。

    一、内存身份认证

      In-Memory Authentication(内存身份认证)是最简单的身份认证方式,主要用于Security安全认证体验和测试

    1.自定义WebSecurityConfigurerAdapter配置类

     2.使用内存进行身份认证

    //开启MVC Security安全支持
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        public void configure(AuthenticationManagerBuilder auth) throws Exception {
            // 密码需要设置编码器
            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
            // 1、使用内存用户信息,作为测试使用
            auth.inMemoryAuthentication().passwordEncoder(encoder)
                    .withUser("czy").password(encoder.encode("123")).roles("common")
                    .and()
                    .withUser("tom").password(encoder.encode("456")).roles("vip");
        }
    }

     3.效果测试

     输入正确的用户名和密码后进入首页

     输入错误的用户名或者密码,将会显示错误

    二、JDBC身份认证

    1.数据准备

    创建t_customer、t_authority和t_customer_authority三张表

    # 选择使用数据库
    USE springbootdata;
    # 创建表t_customer并插入相关数据
    DROP TABLE IF EXISTS `t_customer`;
    CREATE TABLE `t_customer` (
      `id` int(20) NOT NULL AUTO_INCREMENT,
      `username` varchar(200) DEFAULT NULL,
      `password` varchar(200) DEFAULT NULL,
      `valid` tinyint(1) NOT NULL DEFAULT '1',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
    INSERT INTO `t_customer` VALUES ('1', 'shitou', '$2a$10$5ooQI8dir8jv0/gCa1Six.GpzAdIPf6pMqdminZ/3ijYzivCyPlfK', '1');
    INSERT INTO `t_customer` VALUES ('2', '李四', '$2a$10$5ooQI8dir8jv0/gCa1Six.GpzAdIPf6pMqdminZ/3ijYzivCyPlfK', '1');
    # 创建表t_authority并插入相关数据
    DROP TABLE IF EXISTS `t_authority`;
    CREATE TABLE `t_authority` (
      `id` int(20) NOT NULL AUTO_INCREMENT,
      `authority` varchar(20) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
    INSERT INTO `t_authority` VALUES ('1', 'ROLE_common');
    INSERT INTO `t_authority` VALUES ('2', 'ROLE_vip');
    # 创建表t_customer_authority并插入相关数据
    DROP TABLE IF EXISTS `t_customer_authority`;
    CREATE TABLE `t_customer_authority` (
      `id` int(20) NOT NULL AUTO_INCREMENT,
      `customer_id` int(20) DEFAULT NULL,
      `authority_id` int(20) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
    INSERT INTO `t_customer_authority` VALUES ('1', '1', '1');
    INSERT INTO `t_customer_authority` VALUES ('2', '2', '2');
    SQL

    2.添加JDBC连接数据库的依赖启动器

     3、数据库连接配置

    #MySQL相关配置
    spring.datasource.url=jdbc:mysql://192.168.152.120:3306/springbootdata?serverTimeZone=UTC
    spring.datasource.username=root
    spring.datasource.password=1
    #Redis相关配置
    spring.redis.host=192.168.152.120
    spring.redis.port=6379
    spring.redis.password=1

    4、使用JDBC进行身份认证

     // 2.使用JDBC进行身份验证
            String userSQL ="select username,password,valid from t_customer "+ "where username = ?";
            String authoritySQL="select c.username,a.authority from t_customer c, "+"t_authority     a,t_customer_authority ca where "+"ca.customer_id=c.id and ca.authority_id=a.id and     c.username =?";
            auth.jdbcAuthentication().passwordEncoder(encoder).dataSource(dataSource)
                    .usersByUsernameQuery(userSQL).authoritiesByUsernameQuery(authoritySQL);

    5、效果测试:同理

    三、UserDetailsService身份认证

    1、定义查询用户及角色信息的服务接口

    package com.uos.safe.service;
    
    import com.uos.safe.domain.Authority;
    import com.uos.safe.domain.Customer;
    import com.uos.safe.repository.AuthorityRepository;
    import com.uos.safe.repository.CustomerRepository;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.stereotype.Service;
    import java.util.List;
    
    //对用户数据结合Redis缓存进行业务处理
    @Service
    public class CustomerService {
        @Autowired
        private CustomerRepository customerRepository;
        @Autowired
        private AuthorityRepository authorityRepository;
        @Autowired
        private RedisTemplate redisTemplate;
    
        //业务控制:使用唯一用户名查询用户信息
        public Customer getCustomer(String username){
            Customer customer = null;
            Object o = redisTemplate.opsForValue().get("customer_"+username);
            if (o != null){
                customer = (Customer) o;
            }else {
                customer = customerRepository.findByUsername(username);
                if (customer != null){
                    redisTemplate.opsForValue().set("customer_"+username,customer);
                }
            }
            return customer;
        }
        // 业务控制:使用唯一用户名查询用户权限
        public List<Authority> getCustomerAuthority(String username){
            List<Authority> authorities = null;
            Object o = redisTemplate.opsForValue().get("authorities_"+username);
            if (o != null){
                authorities = (List<Authority>) o;
            }else {
                authorities = authorityRepository.findAuthoritiesByUsername(username);
                if (authorities.size() > 0){
                    redisTemplate.opsForValue().set("authorities_"+username,authorities);
                }
            }
            return authorities;
        }
    }
    CustomerService

    2、定义UserDetailsService用于封装认证用户信息

    package com.uos.safe.service;
    
    import com.uos.safe.domain.Authority;
    import com.uos.safe.domain.Customer;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.core.authority.SimpleGrantedAuthority;
    import org.springframework.security.core.userdetails.User;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    import java.util.stream.Collectors;
    
     /*自定义一个 UserDetailsService实现类进行用户认证信息封装*/
    @Service
    public class UserDetailsServiceImpl implements UserDetailsService {
        @Autowired
        CustomerService customerService;
        @Override
        public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
            // 通过业务方法获取用户权限信息
            Customer customer = customerService.getCustomer(s);
            List<Authority> authorities = customerService.getCustomerAuthority(s);
            // 对用户权限进行封装
            List<SimpleGrantedAuthority> list = authorities.stream()
                    .map(authority -> new SimpleGrantedAuthority(authority.getAuthority()))
                    .collect(Collectors.toList());
            // 返回封装的UserDetails用户详情类
            if (customer != null) {
                UserDetails userDetails = new User(customer.getUsername(),customer.getPassword(),list);
                return userDetails;
            } else {
              // 如果查询的用户不存在(用户名不存在),必须抛出异常
              throw new UsernameNotFoundException("当前用户不存在!");
            }
        }
    }
    UserDetailsServiceImpl

    3、使用UserDetailsService进行身份认证

     4、效果测试:同理

  • 相关阅读:
    JFreeChart(一)
    database link 使用<转>
    Hibernate注解配置N:N关联
    JFreeChart(二)
    struts2中<s:doubleselect/>标签的使用心得<原创>
    JSP引入JFreeChart
    struts2中<s:doubleselect/>标签的使用<转>
    Hibernate实体注解配制
    数据库事务隔离级别<转>
    tnsname.ora 个参数解释
  • 原文地址:https://www.cnblogs.com/my-program-life/p/12076474.html
Copyright © 2011-2022 走看看