security基于数据库的认证

目的:登录用户名密码     获取到数据库中的用户 、密码以及权限,根据不同用户以及不同权限,可访问的路径权限也受到限制。

这边用一个小的案例,来体现大体的security权限思想。

1、首先先根据数据库  创建实体类User   实现UserDetails这个接口

/**
 * @Author fei
 * @Date 2021/1/3 7:42 下午
 *
 * 如果自己要在数据库中加载用户,那user类就要实现UserDetails这个接口 然后实现里面的方法
 */
public class User implements UserDetails {
    private Integer id;

    private String username;

    private String password;

    private Boolean enabled;

    private Boolean locked;

    private List<Role> roleList;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @Override
    public String getUsername() {
        return username;
    }

    /**
     * isAccountNonExpired  表示账户是否未过期
     * 返回true   表示 是没有过期
     * @return
     */
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    /**
     * isAccountNonLocked 账户是否未锁定
     * @return
     */
    @Override
    public boolean isAccountNonLocked() {
        //因为这边 是  账户是否未被锁定,而数据库中是没有锁定为false  所以这里要取反
        return !locked;  //在数据库中正好有这个字段,就不要写死了  返回locked就行。这个相当于get方法,所以要将原来该字段的get方法删掉,否则就重复了。
    }

    /**
     * isCredentialsNonExpired 密码是否未过期
     * @return
     */
    @Override
    public boolean isCredentialsNonExpired() {
        return true; //没有过期
    }

    /**
     * 是否可用
     * @return
     */
    @Override
    public boolean isEnabled() {
        return enabled;//本身也有这个字段,则直接返回。去掉原有的get方法。
    }

    public void setUsername(String username) {
        this.username = username;
    }

    /**
     * 这个集合是用来返回用户的所有角色。
     * @return
     */
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        for (Role role : roleList) {
            //返回的所有角色必须前面有 ROLE_ ,没有回报错,如果数据库中本身就是以这个开头,就可以不用写
            authorities.add(new SimpleGrantedAuthority("ROLE_"+role.getName()));

        }
        return authorities;
    }

    @Override
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

//    public Boolean getEnabled() {
//        return enabled;
//    }

    public void setEnabled(Boolean enabled) {
        this.enabled = enabled;
    }

//    public Boolean getLocked() {
//        return locked;
//    }

    public void setLocked(Boolean locked) {
        this.locked = locked;
    }

    public List<Role> getRoleList() {
        return roleList;
    }

    public void setRoleList(List<Role> roleList) {
        this.roleList = roleList;
    }
}

2、在Service层同样要 实现UserDetailsService

/**
 * @Author fei
 * @Date 2021/1/3 8:43 下午
 *
 * 同样userService也要实现UserDetailsService,同时实现里面的方法。因为这边要执行登录的逻辑
 */
@Service
public class UserService implements UserDetailsService {

    @Autowired
    UserMapper userMapper;

    /**
     * 这个方法就是根据用户名来查询用户,有了这个方法都是走这个方法,找不到则抛出异常
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userMapper.loadUserByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("用户不存在!");
        }

        //如果不是空 则需要查询该用户角色
        user.setRoleList(userMapper.getUserRolesById(user.getId()));

        return user; //查到之后就返回,至于填的密码,和他本身的密码,由security自己去比较。我们只要查到就行,查不到就抛异常。
    }
}

3、  数据库xml

<mapper namespace="com.ppf.securitydb.mapper.UserMapper">
    <select id="loadUserByUsername" resultType="com.ppf.securitydb.bean.User">
        select * from user where username = #{username}
    </select>

    <select id="getUserRolesById" resultType="com.ppf.securitydb.bean.Role">
        select * from role where id in(select rid from user_role where uid = #{id})   //user_role是关联用户所对应的角色的表
    </select>


</mapper>

4、 配置securityConfig    这边很重要

/**
 * @Author fei
 * @Date 2021/1/4 10:26 下午
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    UserService userService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService); //这边表示用上数据库里面的用户
    }


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


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/dba/**").hasRole("dba")
                .antMatchers("/admin/**").hasRole("admin")
                .antMatchers("/user/**").hasRole("user")
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .permitAll()
                .and()
                .csrf().disable();
    }
}

 

5、Controller层  写几个方法,来测试权限

/**
 * @Author fei
 * @Date 2021/1/4 10:36 下午
 */
@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello(){
        return "hello security!";
    }

    @GetMapping("/dba/hello")
    public String dba(){
        return "hello dba!";
    }

    @GetMapping("/admin/hello")
    public String admin(){
        return "hello admin!";
    }

    @GetMapping("/user/hello")
    public String user(){
        return "hello user!";
    }



}

6、 最后得出结果,只有所对应用户的角色  才能进入相应的路径。

比如  admin  数据库中密码为 $2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq     (实际解密后123)

角色只是为admin   所以只能  /admin/hello  其他用户的和dba的无权进入。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值