栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringSecurity Web 权限方案

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringSecurity Web 权限方案

用户认证:

**第一种方式:**通过配置文件

spring.security.user.name=atguigu
spring.security.user.password=atguigu

这时控制台不再打印密码;

**第二种方式:**通过配置类
在config包下新建SecurityConfig配置类:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String password = passwordEncoder.encode("123");
        auth.inMemoryAuthentication().withUser("lucy").password(password).roles("admin");
    }

}

这时访问输入用户名密码只会停留在登录页面,IDEA控制台报错。

在配置类中添加:

@Bean
    PasswordEncoder password() {
        return new BCryptPasswordEncoder();
    }


**第三种方式:**自定义编写实现类(常用)
新建一个SecurityConfigTest配置类:

@Configuration
public class SecurityConfigTest extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(password());
    }

    @Bean
    PasswordEncoder password() {
        return new BCryptPasswordEncoder();
    }
}

在service包下新建MyUserDetailsService类实现UserDetailsService接口;

@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        List auths =
                AuthorityUtils.commaSeparatedStringToAuthorityList("role");
        return new User("marry", new BCryptPasswordEncoder().encode("123"),auths);
    }
}

测试:

总结:

通过查询数据库完成认证:
引入依赖:


        
            com.baomidou
            mybatis-plus-boot-starter
            3.0.5
        
        
        
            mysql
            mysql-connector-java
        
        
        
            org.projectlombok
            lombok
        

application.properties添加数据库配置:

#mysql数据库连接
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/demo?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root

在entity包下新建Users类:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Users {
    private Integer id;
    private String username;
    private String password;
}

在mapper包下新建UsersMapper接口:

@Repository
public interface UsersMapper extends baseMapper {
}

更改service包下MyUserDetailsService中的代码:

@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {

    @Autowired
    private UsersMapper usersMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //调用usersMapper方法,根据用户名查询数据库
        QueryWrapper wrapper = new QueryWrapper();
        // where username=?
        wrapper.eq("username",username);
        Users users = usersMapper.selectOne(wrapper);
        //判断
        if(users == null) {//数据库没有用户名,认证失败
            throw  new UsernameNotFoundException("用户名不存在!");
        }
        List auths =
                AuthorityUtils.commaSeparatedStringToAuthorityList("admin,ROLE_sale");
        //从查询数据库返回users对象,得到用户名和密码,返回
        return new User(users.getUsername(),
                new BCryptPasswordEncoder().encode(users.getPassword()),auths);
    }
}

在配置类或者启动类添加:

@MapperScan("com.atguigu.securitydemo1.mapper")
@EnableGlobalMethodSecurity(securedEnabled=true,prePostEnabled = true)


总结:

自定义用户登录页面:
在config包下SecurityConfigTest类中添加如下代码:

@Override
    protected void configure(HttpSecurity http) throws Exception {

        http.formLogin()   //自定义自己编写的登录页面
                .loginPage("/login.html")  //登录页面设置
                .loginProcessingUrl("/user/login")   //登录访问路径
                .defaultSuccessUrl("/test/index").permitAll()  //登录成功之后,跳转路径
                .and().authorizeRequests()
                    .antMatchers("/","/test/hello","/user/login").permitAll() //设置哪些路径可以直接访问,不需要认证
                .anyRequest().authenticated()
                .and().csrf().disable();//关闭csrf保护
    }

在resources包下static目录下新建login.html:




    
    Title


    
用户名:
密码:

注意:name和password的值必须写成username,password,否则SpringSecurity识别不了;
controller添加如下配置:

 @GetMapping("index")
    public String index() {
        return "hello index";
    }

访问localhost:8111/test/hello 可以直接访问;

访问localhost:8111/test/index:


总结:

用户授权:

基于角色或权限进行访问控制:
修改config包下SecurityConfigTest类中代码:

@Override
    protected void configure(HttpSecurity http) throws Exception {

        http.formLogin()   //自定义自己编写的登录页面
                .loginPage("/login.html")  //登录页面设置
                .loginProcessingUrl("/user/login")   //登录访问路径
                .defaultSuccessUrl("/test/index").permitAll()  //登录成功之后,跳转路径
                .and().authorizeRequests()
                .antMatchers("/","/test/hello","/user/login").permitAll() //设置哪些路径可以直接访问,不需要认证
                //当前登录用户,只有具有admins权限才可以访问这个路径
                //1 hasAuthority方法
                .antMatchers("/test/index").hasAuthority("admins")
                .anyRequest().authenticated()
                .and().csrf().disable();//关闭csrf保护
    }


权限不匹配时出现如下页面,表示没有访问权限:

权限改为admins:

@Override
    protected void configure(HttpSecurity http) throws Exception {

        http.formLogin()   //自定义自己编写的登录页面
                .loginPage("/login.html")  //登录页面设置
                .loginProcessingUrl("/user/login")   //登录访问路径
                .defaultSuccessUrl("/test/index").permitAll()  //登录成功之后,跳转路径
                .and().authorizeRequests()
                .antMatchers("/","/test/hello","/user/login").permitAll() //设置哪些路径可以直接访问,不需要认证
                //当前登录用户,只有具有admins权限才可以访问这个路径
                //1 hasAuthority方法
                //.antMatchers("/test/index").hasAuthority("admins")
                //2 hasAnyAuthority方法
                //.antMatchers("/test/index").hasAnyAuthority("admins,manager")
                //3 hasRole方法   ROLE_sale
                .antMatchers("/test/index").hasRole("sale")
                .anyRequest().authenticated()
                .and().csrf().disable();//关闭csrf保护
    }



自定义403页面:
static下新建unauth.html页面:




    
    Title


    

没有访问权限!


注解使用:

用户注销:
config包下修改SecurityConfigTest类:

 @Override
    protected void configure(HttpSecurity http) throws Exception {
        //退出
        http.logout().logoutUrl("/logout").
                logoutSuccessUrl("/test/hello").permitAll();

        //配置没有权限访问跳转自定义页面
        http.exceptionHandling().accessDeniedPage("/unauth.html");

        http.formLogin()   //自定义自己编写的登录页面
                .loginPage("/login.html")  //登录页面设置
                .loginProcessingUrl("/user/login")   //登录访问路径
                .defaultSuccessUrl("/success.html").permitAll()  //登录成功之后,跳转路径
                .failureUrl("/unauth.html")
                .and().authorizeRequests()
                .antMatchers("/","/test/hello","/user/login").permitAll() //设置哪些路径可以直接访问,不需要认证
                //当前登录用户,只有具有admins权限才可以访问这个路径
                //1 hasAuthority方法
                //.antMatchers("/test/index").hasAuthority("admins")
                //2 hasAnyAuthority方法
                //.antMatchers("/test/index").hasAnyAuthority("admins,manager")
                //3 hasRole方法   ROLE_sale
                .antMatchers("/test/index").hasRole("sale")
                .anyRequest().authenticated()
                .and().csrf().disable();//关闭csrf保护
    }

新建success.html页面:




    
    Title


    登录成功!
    退出


输入用户名密码登录时:

点击退出时:


自动登录(原理分析):

自动登录(功能实现):
login.html:




    
    Title


用户名:
密码:
自动登录

此处:name 属性值必须为 remember-me.不能改为其他值
config包下SecurityConfigTest类中修改:

@Override
    protected void configure(HttpSecurity http) throws Exception {
        //退出
        http.logout().logoutUrl("/logout").
                logoutSuccessUrl("/test/hello").permitAll();

        //配置没有权限访问跳转自定义页面
        http.exceptionHandling().accessDeniedPage("/unauth.html");

        http.formLogin()   //自定义自己编写的登录页面
                .loginPage("/login.html")  //登录页面设置
                .loginProcessingUrl("/user/login")   //登录访问路径
                .defaultSuccessUrl("/success.html").permitAll()  //登录成功之后,跳转路径
                .failureUrl("/unauth.html")
                .and().authorizeRequests()
                .antMatchers("/","/test/hello","/user/login").permitAll() //设置哪些路径可以直接访问,不需要认证
                //当前登录用户,只有具有admins权限才可以访问这个路径
                //1 hasAuthority方法
                //.antMatchers("/test/index").hasAuthority("admins")
                //2 hasAnyAuthority方法
                //.antMatchers("/test/index").hasAnyAuthority("admins,manager")
                //3 hasRole方法   ROLE_sale
                .antMatchers("/test/index").hasRole("sale")

                .anyRequest().authenticated()
                .and().rememberMe().tokenRepository(persistentTokenRepository())
                .tokenValiditySeconds(600)//设置有效时长,单位秒
                .userDetailsService(userDetailsService)
                .and().csrf().disable();//关闭csrf保护
    }



CSRF:

概念理解:
跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click
attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的 Web 应用程序上执行非本意的操作的攻击方法。跟跨网站脚本(XSS)相比,XSS利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。
跨站请求攻击,简单地说,是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去运行。这利用了 web 中用户身份验证的一个漏洞:简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。
从 Spring Security 4.0 开始,默认情况下会启用 CSRF 保护,以防止 CSRF 攻击应用程序,Spring Security CSRF 会针对 PATCH,POST,PUT 和 DELETE 方法进行防护。

第一步:
配置类开启:

//关闭csrf保护功能
//http.csrf().disable();

第二步:页面中添加隐藏项。


Spring Security 实现 CSRF 的原理:

  1. 生成 csrfToken 保存到 HttpSession 或者 cookie 中。


  2. 请求到来时,从请求中提取 csrfToken,和保存的 csrfToken 做比较,进而判断当
    前请求是否合法。主要通过 CsrfFilter 过滤器来完成。
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/458938.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号