spring security - 快速整合 springboot

1.引入依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

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

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.3.1</version>
        </dependency>


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<GrantedAuthority> authorityList = new ArrayList<>();
            // 查询当前用户 - 角色信息
            List<Role> roleList = roleService.getRoleListByUserId(bizUser.getId());
            for (Role role : roleList) {
                authorityList.add(new SimpleGrantedAuthority("ROLE_" + role.getRoleCode()));
            }
            // 查询当前用户 - 权限信息
            List<Perms> 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<? extends GrantedAuthority> authorities) {
        super(user.getUserName(), user.getPassword(), true,true, true, true, authorities);
        this.bizUser = user;
    }

    public SecurityUser(String username, String password, Collection<? extends GrantedAuthority> 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);

大体整合完成!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值