Spring Security 简单实现

 

Spring Security(官网地址:https://spring.io/projects/spring-security)是Spring家族的安全框架

 

依赖配置

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

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

 

SecurityConfig

使用Spring Security进行安全管理需要使SecurityConfig继承WebSecurityConfigurerAdapter类,并且使用HttpSecurity的一些安全策略进行配置。

• authorizeRequests:配置一些资源或链接的权限认证。

• antMatchers:配置哪些资源或链接需要被认证。

• permitAll:设置完全允许访问的资源和链接。

• hasRole:配置需要认证的资源或链接的角色。需要注意,若这里需要配置权限为USER,则用户需要拥有权限ROLE_USER,这就是初始化脚本中权限内容修改的原因。

• formLogin:设置form表单提交配置。

• loginPage:设置一个自定义的登录页面URL。

• failureUrl:设置一个自定义的登录失败的URL。

• successForwardUrl:设置一个登录成功后自动跳转的URL。

• accessDeniedPage:设置拒绝访问的URL。

• logoutSuccessUrl:设置退出登录的URL。

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private RoleRepository roleRepository;
    @Autowired
    private MyUserDetailsService myUserDetailsService;

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        //配置资源文件 其中/css/**,/index可以任意访问,/select需要USER权限,/delete需要ADMIN权限
        httpSecurity
                .authorizeRequests()
                .antMatchers("/css/**", "/index").permitAll()
                .antMatchers("/select").hasRole("USER")
                .antMatchers("/delete").hasRole("ADMIN");
        //动态加载数据库中角色权限
        List<Role> roleList = roleRepository.findAll();
        for (Role role : roleList) {
            List<Menu> menuList = role.getMenuList();
            for (Menu menu : menuList) {
                //在SpringSecurity校验权限的时候,会自动将权限前面加ROLE_,所以我们需要 将我们数据库中配置的ROLE_截取掉。
                String roleName = role.getRoleName().replace("ROLE_", "");
                String menuName = "/" + menu.getMenuName();
                httpSecurity
                        .authorizeRequests()
                        .antMatchers(menuName)
                        .hasRole(roleName);
            }
        }
        //配置登录请求/login 登录失败请求/login_error 登录成功请求/
        httpSecurity
                .formLogin()
                .loginPage("/login")
                .failureUrl("/login_error")
                .successForwardUrl("/");
        //登录异常,如权限不符合 请求/401
        httpSecurity
                .exceptionHandling().accessDeniedPage("/401");
        //注销登录 请求/logout
        httpSecurity
                .logout()
                .logoutSuccessUrl("/logout");
    }

    @Bean
    public static NoOpPasswordEncoder passwordEncoder() {
        return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
    }


    //根据用户名密码实现登录
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder
                .inMemoryAuthentication()
                //.passwordEncoder(new BCryptPasswordEncoder())
                .withUser("test").password("123").roles("USER")
                .and()
                .withUser("admin").password("123").roles("ADMIN", "USER");
        authenticationManagerBuilder.userDetailsService(myUserDetailsService);
    }
}

 

MyUserDetailsService

使用数据库认证用户需要自定义一个类来实现UserDetailsService重写loadUserByUsername方法进行认证授权

@Service
public class MyUserDetailsService implements UserDetailsService {
    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUserName(username);
        if (user == null) {
            throw new UsernameNotFoundException("用户不存在!");
        }
        List<SimpleGrantedAuthority> simpleGrantedAuthorities = new ArrayList<>();
        for (Role role : user.getRoleList()) {
            simpleGrantedAuthorities.add(new SimpleGrantedAuthority(role.getRoleName()));
        }
        return new org.springframework.security.core.userdetails.User(user.getUserName(), user.getPassWord(), simpleGrantedAuthorities);
    }
}

 

Controller

@Controller
@Api(tags = "TestSecurityController")
public class TestSecurityController {

    private static final Logger log = LoggerFactory.getLogger(TestSecurityController.class);

    @RequestMapping({"/", "/index"})
    public String index() {
        return "index";
    }

    @RequestMapping("/select")
    public String select() {
        return "select";
    }

    @RequestMapping("/delete")
    public String delete() {
        return "delete";
    }

    @RequestMapping("/login")
    public String login() {
        return "login";
    }

    @RequestMapping("/login_error")
    public String login_error(Model model) {
        model.addAttribute("login_error", "用户名或密码错误");
        return "login";
    }

    @RequestMapping("/logout")
    public String logout(Model model) {
        model.addAttribute("login_error", "注销成功");
        return "login";
    }

    @RequestMapping("/401")
    public String error() {
        return "401";
    }
}

 

 

参考来源:Spring Boot 2实战之旅-7.2 使用Spring Security

源码:https://gitee.com/caoyeoo0/xc-springboot/tree/springSecurity/

 

posted @ 2020-11-23 17:20  草木物语  阅读(320)  评论(0编辑  收藏  举报