SpringBoot 整合Spring Security框架

 

SpringBoot 整合Spring Security + JWT 实现前后端分离项目的认证授权参考 :https://www.cnblogs.com/pxblog/p/16180791.html

 

引入maven依赖

 <!-- 放入spring security依赖  -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

 

 

Spring Security配置类

SecurityConfig.java

import org.springframework.context.annotation.Bean;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * 配置类
 * @EnableWebSecurity 开启Security功能
 */
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)  //允许通过注解的方法拦截
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    /**
     * 用于密码加密
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    /**
     * 进行授权
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception{
        /**
         *定制请求的授权规则
         *  permitAll() 表示都允许访问
         *  hasRole("admin") 表示用户必须有admin的角色才能访问
         */

        http.authorizeRequests().antMatchers("/").permitAll()
                .antMatchers("/add").hasRole("admin");

        /**
         * 开启自动配置的登录功能,如果没有权限就会来到登录页面
         * 1、 /login 请求进入登录页,可自定义
         *      表单的用户名name 默认为username
         *           密码name 默认为 password
         *
         *           usernameParameter 参数可以设置表单中用户名的name
         *           passwordParameter 参数可以设置表单中密码的name
         *
         * 2、重定向到/login?error 表示登录失败
         * 定义登录页 /toLogin 请求
         * loginProcessingUrl("") 设置登录提交的请求链接
         */
        http.formLogin().
                loginPage("/toLogin")
                .usernameParameter("username")
                .passwordParameter("pwd")
                .loginProcessingUrl("/login");


        /**
         * 关闭csrf功能,禁用跨站请求,进行安全访问
         */
        http.csrf().disable();


        /**
         * 开启记住我功能,登录信息保存cookie,
         * 默认保存两周
         * rememberMeParameter 参数设置表单中 记住我 的name名
         */
        http.rememberMe().rememberMeParameter("rememberMe");

        /**
         * 开启自动配置的注销功能
         * 1、访问 logout 表示用户注销,清空session
         * 可以通过
         *         Authentication authentication=SecurityContextHolder.getContext().getAuthentication();
         *         authentication.getPrincipal();  获取登录用户信息
         *
         *
         *
         * 2、注销成功默认会请求 /login?logout (登录页面)
         * 可以通过logoutSuccessUrl() 方法自定义退出成功后的地址
         */
        http.logout().logoutSuccessUrl("/");


    }

    /**
     * 认证  springboot 2.1.x可以直接使用
     * 密码编码 :passwordEncoder
     * 在spring security 5.0+ 新增了加密方法
     *
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception{
        auth.userDetailsService(new UserServiceConfig());
    }
}

 

Spring Security 查询用户信息类

UserServiceConfig.java

import com.example.demo.entity.CmsUser;
import com.example.demo.entity.Role;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
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.security.crypto.password.PasswordEncoder;

import java.util.ArrayList;
import java.util.List;

@Configuration
public class UserServiceConfig implements UserDetailsService {


    @Autowired
    private PasswordEncoder passwordEncoder;


    @Autowired
    private UserService userService;


    /**
     * 根据用户名查找用户
     * @param username  用户在浏览器输入的用户名
     * @return UserDetails 是spring security自己的用户对象
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        CmsUser cmsUser =userService.findByUsername(username);

        if (cmsUser==null){
            //表示查询不到用户,认证失败
            return null;
        }

        /**
         * 这里为了演示进行了密码加密,实际开发中应该是用户在进行注册时就对密码进行加密,
         * 这里直接取数据库的密码进行比对即可,不需要再进行加密
         */
        String password=passwordEncoder.encode(cmsUser.getPassword());


        /**
         * 添加该用户的角色信息
         * roleName 是角色名称
         */
        List<SimpleGrantedAuthority> authorities=new ArrayList<>();
        List<Role> roles=cmsUser.getRoles();
        for (Role role:roles){
            authorities.add(new SimpleGrantedAuthority(role.getRoleName()));
        }


        return new User(cmsUser.getUsername(),password,authorities);
    }



}

 

 

自定义错误页面

ErrorPageConfig.java

package com.example.demo.security;


import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.ErrorPageRegistrar;
import org.springframework.boot.web.server.ErrorPageRegistry;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;


/**
 * 定制错误页面
 */
@Configuration
public class ErrorPageConfig implements ErrorPageRegistrar {


    @Override
    public void registerErrorPages(ErrorPageRegistry registry) {

        /**
         * 定制禁止访问错误页面
         *  /403 是错误页面的跳转请求
         */
        ErrorPage errorPage=new ErrorPage(HttpStatus.FORBIDDEN,"/403");



        registry.addErrorPages(errorPage);


    }
}

 

posted @ 2020-05-24 19:42  yvioo  阅读(361)  评论(0编辑  收藏  举报