Loading

springsecrity入门demo 认证

创建一个springboot项目

springboot版本依赖 使用 2.3.12.RELEASE

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.4</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>
    </dependencies>

用户表

DROP TABLE IF EXISTS `t_admin`;
CREATE TABLE `t_admin`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `create_time` bigint(32) NOT NULL COMMENT '创建时间',
  `enabled` tinyint(2) NOT NULL DEFAULT 0 COMMENT '是否启用: 0 不启动,1 启用',
  `name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '姓名',
  `password` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '密码',
  `update_time` bigint(32) NOT NULL COMMENT '更新时间',
  `username` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户名',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'Admin对象 用户表' ROW_FORMAT = Dynamic;

配置文件

spring:
  datasource:
    name: 
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://:3310/?characterEncoding=utf8&useSSL=false
    username: root
    password: 密码

创建用户类


public class Admin implements Serializable, UserDetails {

    private static final long serialVersionUID = 1L;

    private Long id;
    private Long createTime;
    private boolean enabled;
    private String name;
    private String password;
    private Long updateTime;
    private String username;
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public Long getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Long createTime) {
        this.createTime = createTime;
    }
    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public Long getUpdateTime() {
        return updateTime;
    }
    public void setUpdateTime(Long updateTime) {
        this.updateTime = updateTime;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    @Override
    public String toString() {
        return "Admin{" +
                "id=" + id +
                ", createTime=" + createTime +
                ", enabled=" + enabled +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' +
                ", updateTime=" + updateTime +
                ", username='" + username + '\'' +
                '}';
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }
    @Override
    public String getPassword() {
        return password;
    }
    @Override
    public String getUsername() {
        return username;
    }
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
    @Override
    public boolean isEnabled() {
        return this.enabled;
    }
}

新建mapper

public interface AdminMapper extends BaseMapper<Admin> {

    @Select("select * from t_admin " +
            "${ew.customSqlSegment}")
    Admin getAllAdmins(@Param(Constants.WRAPPER) Wrapper wrapper);

}

service

public interface IAdminService extends IService<Admin> {

    Admin getAllAdmins(String name);

}
@Service
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements IAdminService {

    @Resource
    private AdminMapper adminMapper;

    public Admin getAllAdmins(String name) {
        System.out.println(name);
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("name",name);
        return adminMapper.getAllAdmins(queryWrapper);
    }
}

新建UserServiceImpl 实现UserDetailsService

这里实现通过查询数据库返回密码到密码验证类

@Service
public class UserServiceImpl implements UserDetailsService {

    @Autowired
    private AdminServiceImpl adminService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //数据库查询
        Admin allAdmins = adminService.getAllAdmins(username);

        //1.根据username查询数据库
        if(allAdmins==null){
            throw new UsernameNotFoundException("用户名或密码错误");
        }
        return new User(allAdmins.getName(), allAdmins.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
    }
}

新建config需要两个配置类

密码校验UserAuthenticationProvider

把上一个UserDetailsService 类注入进来
重点是这个 方法 bCryptPasswordEncoder.matches(password, userDetails.getPassword());

/**
 * 完成校验工作
 */
@Component
public class UserAuthenticationProvider  implements AuthenticationProvider {
    @Autowired
    private UserDetailsService userDetailService;

    /**
     * 进行身份认证
     *
     * @param authentication
     * @return
     * @throws AuthenticationException
     */
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        System.out.println("进行身份认证");
        // 获取用户输入的用户名和密码
        String username = authentication.getName();
        String password = authentication.getCredentials().toString();
        System.out.println(username);
        // 获取封装用户信息的对象
        UserDetails userDetails = userDetailService.loadUserByUsername(username);
        System.out.println("   ===========   权限:"+userDetails.getAuthorities());
        // 进行密码的比对
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        boolean flag = bCryptPasswordEncoder.matches(password, userDetails.getPassword());
        // 校验通过
        if (flag){
            // 将权限信息也封装进去
            return new UsernamePasswordAuthenticationToken(userDetails.getUsername(), userDetails.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList("admin,normal,rzk"));
        }
        // 验证失败返回 null
        return null;
    }

    /**
     * 这个方法 确保返回 true 即可,
     *
     * @param aClass
     * @return
     */
    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }
}

SecurityConfig


/**
 * @PackageName : com.rzk.config
 * @FileName : SecurityConfig
 * @Description :
 * @Author : rzk
 * @CreateTime : 13/12/2021 下午10:19
 * @Version : v1.0
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        System.out.println("执行自定义登录逻辑方法");
        //表单登录
        http.formLogin()
                //自定义登录页面
                .loginPage("/login.html")
                //自定义登录逻辑
                .loginProcessingUrl("/login")
                //登录成功后跳转的页面,必须是post
                .successForwardUrl("/toMain")
                //登录失败后跳转页面,必须是post
                .failureForwardUrl("/toError");

        //授权
        http.authorizeRequests()
                //放行页面
                .antMatchers("/login.html").permitAll()
                .antMatchers("/error.html").permitAll()
                //所有请求都必须被认证(登录)
                .anyRequest().authenticated();

        //关闭csrf防护
        http.csrf().disable();
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

controller

@Controller
public class LoginController {

    @Autowired
    private IAdminService adminService;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private UserDetailsService userDetailsService;

    @RequestMapping("/login")
    public String login(@RequestParam("username") String username, @RequestParam("password")String password){
        Admin allAdmins = adminService.getAllAdmins(username);
        //登录
        UserDetails userDetails = userDetailsService.loadUserByUsername(username);
        if (userDetails == null || !passwordEncoder.matches(password,allAdmins.getPassword())){
            System.out.println("空");
        }
        return "redirect:main.html";
    }

    @RequestMapping("/toMain")
    public String toMain(){
        return "redirect:main.html";
    }

    @RequestMapping("/toError")
    public String error(){
        return "redirect:error.html";
    }
}

这里需要三个html页面

error.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
登录失败
</body>
</html>

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/login" method="post">
    用户名:<input type="text"name="username"/><br/>
    密码:<input type="password"name="password"/><br/>
    <input type="submit"value="登录"/><br/>
</form>
</body>
</html>

main.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>登录成功</h1>
</body>
</html>

还没登录如果访问登录成功页面 是访问不了的

posted @ 2021-12-18 01:06  Rzk  阅读(69)  评论(0编辑  收藏  举报