使用Spring Security


#使用Spring Security

简介

spring security是一个提供声明式的安全访问控制解决方案的安全框架,为应用系统提供声明式的安全访问功能,减少了为企业系统安全控制编写大量重复代码的工作。
其中,spring security提供了一下功能:
身份认证
授权
加密
会话管理
Session管理
支持HTTP/HTTPS
支持Basic和Digest认证
Remember-Me
CORS
等等等等…
下面是用spring security做简单的登录检测与权限控制

场景及初始化数据

数据库有user,role,menu三个实体,其中两两之间都是多对多的关系。而根据关系数据库设计原理,多对多关系会衍生一个新表,所以,表结构大致如下
图片一

依赖与配置文件点此查看
源码点此查看

@ManytoMany的使用

    @ManyToMany(fetch= FetchType.EAGER)
    @JoinTable(name = "UserRole", joinColumns = { @JoinColumn(name = "userId") },
    inverseJoinColumns ={@JoinColumn(name = "roleId") })
    private List<Role> roleList;

其中(fetch= FetchType.EAGER)的使用需要注意,两边只需要写一个,而不是两变都写,负责就会报错

字段的大小写

使用jpa,若有个属性为password,那么表中就是password,若表中是pass_word,那么就会报错,必须吧属性改成passWord才对。。。这个实在太坑了

MyUserDetailsService

使用数据库认证需要自定义一个类来实现UserDetailsService重写loadUserByUsername方法进行认证授权
也就是说,如果需要结合自己的数据库来进行认证,那么就必须自定义自己的DetailService,并实现loadUserByUsername。
类名前必须加上@Service注释
GrantedAuthority表示已授予的权限

    //username为从前端页面接收到的数据,然后使用jpa查询数据库进行验证

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUserName(username);
        System.out.println(user.getPassWord());
        System.out.println(user.getUserName());
        if (user == null){
            throw new UsernameNotFoundException("用户不存在!");
        }

        //再通过SimpleGrantedAuthority聚合该用户的所有role

        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);
    }

SecurityConfig

SecurityConfig用来进行相关配置
首先配置资源文件,哪些可以访问,哪些需要有权限访问

        //配置资源文件 其中/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");
    }

NoOpPasswordEncoder设置密码不加密

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

configureGlobal根据自己自定义的登录证明或者在内存中加入用户来实现登录
AuthenticationManagerBuilder允许轻松构建内存身份验证
userDetailsService使用自定义的登录证明

    //根据用户名密码实现登录
    @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);
    }

@Controller和@RestController的区别

@RestController注解相当于@ResponseBody + @Controller合在一起的作用。

  1. 如果只是使用@RestController注解Controller,则Controller中的方法无法返回jsp页面,或者html,配置的视图解析器 InternalResourceViewResolver不起作用,返回的内容就是Return 里的内容。

  2. 如果需要返回到指定页面,则需要用 @Controller配合视图解析器InternalResourceViewResolver才行。
    InternalResourceViewResolver不起作用,返回的内容就是Return 里的内容。

  3. 如果需要返回到指定页面,则需要用 @Controller配合视图解析器InternalResourceViewResolver才行。
    如果需要返回JSON,XML或自定义mediaType内容到页面,则需要在对应的方法上加上@ResponseBody注解。

总结

一杯茶一包烟,一个小小的bug就能让你改一天,如果不明白过程或者原理,那么总有一个地方,哪怕是照着敲上去,都会出错。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用Spring Security可以帮助我们实现应用程序的身份验证和授权功能。下面是使用Spring Security的一般步骤: 1. 添加Maven或Gradle依赖项:在项目的构建文件中,添加Spring Security的相关依赖项。通常,需要添加`spring-boot-starter-security`或`spring-security-web`和`spring-security-config`依赖项。 2. 配置Spring Security:创建一个配置类,该类扩展自`WebSecurityConfigurerAdapter`,并覆盖必要的方法来配置安全性设置。您可以使用`@EnableWebSecurity`注解来启用Spring Security。 3. 配置用户和角色信息:在配置类中,您可以使用自定义的用户详细信息服务(实现`UserDetailsService`接口)来加载用户信息,并使用密码编码器(如BCryptPasswordEncoder)对密码进行加密和验证。 4. 配置URL访问规则:使用`http.authorizeRequests()`方法来配置URL路径的访问规则。您可以指定哪些URL需要身份验证,哪些URL不需要身份验证,以及哪些URL需要特定的角色或权限。 5. 配置登录和注销功能:通过覆盖默认的登录和注销行为,您可以自定义登录页面、处理登录请求以及注销操作。 6. 配置访问拒绝处理:如果用户尝试访问他们没有权限的页面,您可以配置一个访问拒绝处理器,以便为他们显示适当的错误页面或重定向。 这只是使用Spring Security的基本步骤,您可以根据您的应用程序需求进行更详细的配置和自定义。您可以参考Spring Security的官方文档和示例代码来获取更多信息和示例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值