springboot,整合springsecurity登录认证和授权

最近学习了下springserurity登录认证操作,记录下学习整合的过程:
框架:springboot+mybatis+springsecurity

登录认证

1 新建一个页面,路径resource/html/hello.html,做一个访问它需要账号密码的功能。
修改了默认的访问页面资源路径为resource/html/ ,application.properies文件中

spring.thymeleaf.prefix=classpath:/html/
spring.thymeleaf.suffix=.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org"
      xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
    <title>Hello World!</title>
</head>
<body>
<h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
<form th:action="@{/logout}" method="post">
    <input type="submit" value="Sign Out"/>
</form>
</body>
</html>

2 引入springsecurity 依赖

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

3 配置需要认证的页面,新增配置类继承WebSecurityConfigurerAdapter并重写 configure(HttpSecurity http)方法和configure(AuthenticationManagerBuilder auth)

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //路径/和/home不需要访问控制
        http
                .authorizeRequests()
                // 如果有允许匿名的url,填在下面,/和/home 放行
                .antMatchers("/", "/home").permitAll()
                .anyRequest().authenticated()
                .and()
                //自定义登录页面login.html
                .formLogin()
                .loginPage("/login").permitAll()

                .and()
                .logout().permitAll();
    }
		 @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // TODO Auto-generated method stub
        //inMemoryAuthentication 从内存中获取 //auth.inMemoryAuthentication().withUser("JACK").password("123").roles("ADMIN");
             auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()).withUser("JACK").
                password(new BCryptPasswordEncoder().encode("123")).roles("USER");
  
    }
 }

一开始我用auth.inMemoryAuthentication().withUser(“JACK”).password(“123”).roles(“ADMIN”);来指定认证用户,没认证成功,而且IDEA有报错:java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id “null”,网上查了一下因为Spring security 5.0中新增了多种加密方式,也改变了密码的格式。官方文档
在这里插入图片描述
上面这段话的意思是说,现如今Spring Security中密码的存储格式是“{id}…………”。前面的id是加密方式,id可以是bcrypt、sha256等,后面跟着的是加密后的密码。也就是说,程序拿到传过来的密码的时候,会首先查找被“{”和“}”包括起来的id,来确定后面的密码是被怎么样加密的,如果找不到就认为id是null。这也就是为什么我们的程序会报错:There is no PasswordEncoder mapped for the id “null”。官方文档举的例子中是各种加密方式针对同一密码加密后的存储形式,原始密码都是“password”。

原文链接:https://blog.csdn.net/canon_in_d_major/article/details/79675033

4 自定义登录页面

<!doctype html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org"
      xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
    <meta charset="UTF-8" />
    <title>login</title>
</head>
<body>
<div th:if="${param.error}">无效用户名和密码</div>
<div th:if="${param.logout}">已登出</div>
<form th:action="@{/login}" method="post">
    <div>User Name: <input type="text" name="username" /></label></div>
    <div>password: <input type="password" name="password" /></label></div>
    <div><input type="submit" value="Sign In"/></div>
</form>
</body>
</html>

5 启动springboot应用,浏览器输入http://localhost:8081/hello,会跳转到登录认证界面http://localhost:8081/login,
在这里插入图片描述
输入正确后
在这里插入图片描述
这种是自己设定固定的密码,现实情况应该是从数据库查找账户密码,然后比对输入的。所以我们来改一下,Mbatis整合就不多说了,还有新建User类用来封数据也不提了:
在这里插入图片描述

1 在上面的基础上增加和修改,新建一个service ,实现UserDetailsService接口,方法主要作用是根据输入的名字String username,查找数据库的用户,返回带有返回数据库用户信息的org.springframework.security.core.userdetails.User

@Service
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    IUser user;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        //从数据库中根据输入的名字查找用户,返回userinfo
        User userinfo = user.findUserByName(username);
        //把权限属性放到 SimpleGrantedAuthority类,由于一个用户可能有多个权限,因此放到List<SimpleGrantedAuthority> authorities
        List<SimpleGrantedAuthority> authorities = new ArrayList<SimpleGrantedAuthority>();
        authorities.add(new SimpleGrantedAuthority(userinfo.getRoot()));
        //返回org.springframework.security.core.userdetails.User,把数据库查到的用户信息写入,返回作判断
        org.springframework.security.core.userdetails.User user =
                new org.springframework.security.core.userdetails.User(userinfo.getUser(),new BCryptPasswordEncoder().encode(userinfo.getPassword()),true,true,true,true,authorities);

        return user;
    }
}

2 配置类 :auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
这句指定上面的 实际UserDetailsService接口的类,new BCryptPasswordEncoder()是密码的加密方式,对应的上面的类new BCryptPasswordEncoder().encode(userinfo.getPassword()),传入一样的加密方式。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    CustomUserDetailsService userDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //路径/和/home不需要访问控制
        http
                .authorizeRequests()
                // 如果有允许匿名的url,填在下面,/和/home 放行
                .antMatchers("/", "/home").permitAll()
                .anyRequest().authenticated()
                .and()
                //自定义登录页面login.html
                .formLogin()
                .loginPage("/login").permitAll()

                .and()
                .logout().permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // TODO Auto-generated method stub
      //  auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()).withUser("JACK").
     //           password(new BCryptPasswordEncoder().encode("123")).roles("USER");

        auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
    }
}

在这里插入图片描述
再试下其它

@Controller
public class Mycontroller {

    @Autowired
    private IService service;

    @RequestMapping(value = "/hh",method = RequestMethod.GET)
    public String gotoHello(){
       System.out.println("gotoHello");
        return "haha";
    }
}

在这里插入图片描述
在这里插入图片描述

增加授权:

1 修改配置类,添加拦截url的权限 .antMatchers("/hh").hasRole(“ADMIN”),这时候访问http://localhost:8081/hh 就需要登录认证成功 和 “ADMIN”权限才能访问

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //路径/和/home不需要访问控制
        http
                .authorizeRequests()
                // 如果有允许匿名的url,填在下面,/和/home 放行
                .antMatchers("/", "/home").permitAll()
                // "/hh" 权限需要有认证用户的权限限制ADMIN
                .antMatchers("/hh").hasRole("ADMIN")
                .anyRequest().authenticated()
                .and()
                //自定义登录页面login.html
                .formLogin()
                .loginPage("/login").permitAll()

                .and()
                .logout().permitAll();
    }

运行一下,报错,原因是定义的角色名称不匹配,路径权限规则匹配中配置的是:ADMIN ,自定义权限验证中就要配置用户的权限:ROLE_ADMIN 需要加上ROLE_开头
在这里插入图片描述

2 修改 ArrayList();
authorities.add(new SimpleGrantedAuthority(“ROLE_”+userinfo.getRoot()));

   @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        //从数据库中根据输入的名字查找用户,返回userinfo
        User userinfo = user.findUserByName(username);
        //把权限属性放到 SimpleGrantedAuthority类,由于一个用户可能有多个权限,因此放到List<SimpleGrantedAuthority> authorities
        List<SimpleGrantedAuthority> authorities = new ArrayList<SimpleGrantedAuthority>();
        authorities.add(new SimpleGrantedAuthority("ROLE_"+userinfo.getRoot()));
        //返回org.springframework.security.core.userdetails.User,把数据库查到的用户信息写入,返回作判断
        org.springframework.security.core.userdetails.User user =
                new org.springframework.security.core.userdetails.User(userinfo.getUser(),new BCryptPasswordEncoder().encode(userinfo.getPassword()),true,true,true,true,authorities);

        return user;
    }

成功。
在这里插入图片描述
到这里已经登录认证成功了,我再访问其它需要认证的资源时,不会再次跳转login页面再输入账户密码,因为他把用户信息暂存在session里。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值