• spring security - 快速整合 springboot


    1.引入依赖
    
            
                org.springframework.boot
                spring-boot-starter-web
            
    
            
                org.springframework.boot
                spring-boot-starter-security
            
    
            
                mysql
                mysql-connector-java
                8.0.33
                runtime
            
    
            
                org.mybatis.spring.boot
                mybatis-spring-boot-starter
                2.3.1
            
    
    
    2.配置 application.properties
    
    server.port=8086
    #
    spring.application.name=security-sample
    spring.main.allow-bean-definition-overriding=true
    spring.mvc.static-path-pattern=/static/**
    # thymeleaf 配置
    spring.thymeleaf.enabled=true
    spring.thymeleaf.cache=false
    spring.thymeleaf.servlet.content-type=text/html
    spring.thymeleaf.encoding=UTF-8
    spring.thymeleaf.mode=HTML
    spring.thymeleaf.prefix=classpath:/templates/
    spring.thymeleaf.suffix=.html
    
    # 数据库配置
    spring.datasource.name=defaultDataSource
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.url=jdbc:mysql://127.0.0.1:3306/db_plain?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false
    spring.datasource.username=root
    spring.datasource.password=root123
    # 连接池配置
    spring.datasource.type=com.zaxxer.hikari.HikariDataSource
    spring.datasource.hikari.maximum-pool-size=8
    spring.datasource.hikari.minimum-idle=4
    spring.datasource.hikari.connection-timeout=30000
    spring.datasource.hikari.max-lifetime=50000
    spring.datasource.hikari.auto-commit=true
    spring.datasource.hikari.pool-name=HikariCP
    # mybatis 配置
    mybatis.mapper-locations=classpath:mappers/*xml
    mybatis.type-aliases-package=com.sky.biz.entity
    mybatis.configuration.map-underscore-to-camel-case=true
    
    
    3.定制开发 - 认证流程的 UserDetailsService
    
    说明:UserDetailsService 负责在 Security 框架中从数据源中查询出2大主要信息,
    分别为:认证信息(账号、密码)、授权信息(角色列表、权限列表)。随后将这些信息封装为 UserDetails 对象返回
    留作后续进行登录认证以及权限判断。
    
    @Component
    public class UserDetailsServiceImpl implements UserDetailsService {
    
        @Autowired
        private UserService userService;
        @Autowired
        private RoleService roleService;
        @Autowired
        private PermsService permsService;
    
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    
            BizUser bizUser = userService.queryByUserName(username);
            // 用户存在,查询封装用户的"角色与权限"信息到 UserDetails中,通常自定义封装对象,继承 UserDetails的子类 User
            if(bizUser != null) {
                // 使用 authorityList 封装角色权限信息
                List authorityList = new ArrayList<>();
                // 查询当前用户 - 角色信息
                List roleList = roleService.getRoleListByUserId(bizUser.getId());
                for (Role role : roleList) {
                    authorityList.add(new SimpleGrantedAuthority("ROLE_" + role.getRoleCode()));
                }
                // 查询当前用户 - 权限信息
                List permsList = permsService.getPermsListByUserId(bizUser.getId());
                for (Perms perm : permsList) {
                    authorityList.add(new SimpleGrantedAuthority(perm.getPermCode()));
                }
                return new SecurityUser(bizUser, authorityList);
            }
    
            return null;
        }
    
    }
    
    4.定义封装安全信息的实体类:SecurityUser
    
    public class SecurityUser extends User {
    
        private BizUser bizUser;
    
        public SecurityUser(BizUser user, Collection authorities) {
            super(user.getUserName(), user.getPassword(), true,true, true, true, authorities);
            this.bizUser = user;
        }
    
        public SecurityUser(String username, String password, Collection authorities) {
            super(username, password, authorities);
        }
    
        // get && set
        public BizUser getBizUser() {
            return bizUser;
        }
    
        public void setBizUser(BizUser bizUser) {
            this.bizUser = bizUser;
        }
    }
    
    5.自定义密码校验的类:PasswordEncoder,这里自由发挥,根据各自公司安全需要自定义
    
    主要就是重写 encode(CharSequence rawPassword)  和  matches(CharSequence rawPassword, String encodedPassword) 方法
    如果不想自定义就配置成spring-security提供的 BCryptPasswordEncoder 来处理密码加密与校验
    
    6.配置Security
    
    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true) // 开启方法级别的细粒度权限控制
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private UserDetailsService userDetailsService;
    
    
        // 配置对 HTTP 请求的安全拦截处理
        @Override
        protected void configure(HttpSecurity http) throws Exception {
    
            http.authorizeRequests().antMatchers("/static/**").permitAll()
                    .anyRequest().authenticated()
                    .and().formLogin()
                    .and().csrf().disable()
                    .formLogin().loginPage("/login").loginProcessingUrl("/doLogin")
                    .defaultSuccessUrl("/main") 
                    .failureUrl("/fail")  
                    .permitAll();
    
            // "/login","/main"与"/fail",都是对应 html页面访问controller跳转路径
            // 用户权限不够,处理并返回响应
            http.exceptionHandling().accessDeniedHandler(new AccessDeniedHandler() {
                @Override
                public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
    
                    String header = request.getHeader("X-Requested-With");
    
                    if("XMLHttpRequest".equals(header)) {
                        response.getWriter().print("403"); // 返回ajax 请求对应的 json格式
                    } else {
                        request.getRequestDispatcher("/error403").forward(request, response);
                    }
                }
            });
    
        }
    
    
        @Bean
        public MyPasswordEncoder passwordEncoder() {
            return new MyPasswordEncoder();
        }
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    
            auth.userDetailsService(userDetailsService).passwordEncoder(new passwordEncoder());
            // 或者:auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
    
        }
    }
    
    
    7.使用加密时:
        @Autowired
        private MyPasswordEncoder passwordEncoder;
    
        // 方法1:
        String encodePwd = passwordEncoder.encode(user.getPassword());
        // 方法2:
        String encodePwd = new BCryptPasswordEncoder().encode(user.getPassword());
    
        user.setPassword(encodePwd);
    
        userMapper.save(user);
    
    大体整合完成!
    
    
  • 相关阅读:
    Understanding JSON Schema
    RAG下的prompt编写探索
    Java Web实现用户登录功能
    Kubernetes IPVS和IPTABLES
    【笔试题】【day8】
    Spring-IOC-Spring6和JUnit5集成
    ROS2学习(一):Ubuntu 22.04 安装 ROS2(Iron Irwini)
    【STM32】 相关寄存器总结
    iOS中的3种定时器
    星空表白彩蛋 ,游戏是假,爱你是真 --- 俄罗斯方块彩蛋
  • 原文地址:https://blog.csdn.net/qq_19783793/article/details/132678682