天天看点

Spring Security - 用户密码配置

Spring Security 用户密码配置

配置文件

Spring Boot中整合Spring Security只需添加一个依赖即可,非常方便,启动项目时:控制台会输出一个密码,在浏览器访问时会弹出一个登录框,默认用户为user,而密码就是控制台输出的那段字符串。

那这样就会有一个问题,每次访问都需要复制控制台的密码,当然,这个是可以配置的,可以在配置文件当中进行如下配置。

spring.security.user.name=user
spring.security.user.password=youyuan 
           

此时,访问浏览器登录即可。

内存配置

当然也可以基于内存进行配置,创建一个类继承自WebSecurityConfigurerAdapter然后实现其configuration方法即可。

@Configuration 
public class MultiHttpSecurityConfig extend WebSecurityConfigurerAdapter{

    //对密码不进行加密处理
    @Bean
    PasswordEncoder passwordEncoder(){
        return NoOpPasswordEncoder.getInstance();
    }

    @Autowired
    /*用户认证*/
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("youyuan").password("1011").roles("admin")
                .and()
                .withUser("zs").password("1011").roles("user");
    }
}

           

注意:基于内存的用户配置在配置角色时不需要添加"ROLE_ "前缀

数据库配置

当然在实际开发情况下,用户与密码还是要从数据库当中加载,基于数据库进行认证。

首先我们准备三个表,分别为用户,角色,还有用户角色表。用户角色表关联每个用户所对应的角色。

Spring Security - 用户密码配置

在配置基本的数据库信息:

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.password=root
spring.datasource.username=root
spring.datasource.url=jdbc:mysql://localhost:3306/testcharacterEncoding=utf-8&serverTimezone=UTC
           

然后在创建对应的实体类:

@Data
public class User implements UserDetails {
    private Integer id;
    private String username;
    private String password;
    private Boolean enabled;
    private Boolean locked;
    private List<Role> roles;
    @Override
    /*返回用户所有角色*/
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        for (Role role : this.roles) {
            authorities.add(new SimpleGrantedAuthority("ROLE_"+role.getName()));
        }
        return authorities;
    }

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

    @Override
    /*账户是否未锁定*/
    public boolean isAccountNonLocked() {
        return !locked;
    }

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

    @Override
    public boolean isEnabled() {
        return enabled;
    }

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

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


}

           

在UserService类中实现UserDetailsService接口

@Service
public class UserService implements UserDetailsService {

    @Autowired
    UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userMapper.loadUserByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("用户不存在!");
        }
        /**
        *查询出相应的角色
        *添加角色到user中**/
        user.setRoles(userMapper.getUserRolesById(user.getId()));
        return user;
    }
}

           

最后在Spring Security进行配置:

@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()//开启登录配置 
        .anyRequest().authenticated() //表示访问接口,需要进行认证
        .and()
        .formLogin()
        .loginProcessingUrl("/doLogin")
                .loginPage("/login") //默认的登录页面
                .usernameParameter("user")//定义登录时,用户名的 key,默认为 username
                .passwordParameter("pwd") //定义登录时,用户密码的 key,默认为 password
                .successHandler(new AuthenticationSuccessHandler() {
                    @Override
                    public void onAuthenticationSuccess(HttpServletRequest request,
                                                        HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
                        response.setContentType("application/json;charset=utf-8");
                        PrintWriter out = response.getWriter();
                        Map<String,Object> map = new HashMap<>();
                        map.put("status",200);
                        map.put("msg",authentication.getPrincipal());
                        //浏览器返回json数据
                        out.write(new ObjectMapper().writeValueAsString(map));
                        out.flush();
                        out.close();
                    }
                })
                .failureHandler(new AuthenticationFailureHandler() {
                    @Override
                    public void onAuthenticationFailure(HttpServletRequest request,
                                                        HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
                        response.setContentType("application/json;charset=utf-8");
                        PrintWriter out = response.getWriter();
                        Map<String,Object> map = new HashMap<>();
                        map.put("status",401);
                        if (e instanceof LockedException){
                            map.put("msg","账户被锁定,登录失败");
                        }else if (e instanceof BadCredentialsException){
                            map.put("msg","用户名或密码输入错误,登录失败");
                        }else if (e instanceof DisabledException){
                            map.put("msg","账户被禁用,登录失败");
                        }else if(e instanceof AccountExpiredException){
                            map.put("msg","账户过期,登录失败");
                        }else if (e instanceof CredentialsExpiredException){
                            map.put("msg","密码过期,登录失败");
                        }else {
                            map.put("msg","登录失败");
                        }
                        //浏览器返回json数据
                        out.write(new ObjectMapper().writeValueAsString(map));
                        out.flush();
                        out.close();
                    }
                })
        .permitAll()    //和表单登录相关的接口统统都直接通过
        .and()
                .logout()
                .logoutUrl("/logout")
                .logoutSuccessHandler(new LogoutSuccessHandler() {
                    @Override
                    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
                        resp.setContentType("application/json;charset=utf-8");
                        PrintWriter out = resp.getWriter();
                        Map<String,Object> map = new HashMap<>();
                        map.put("status",200);
                        map.put("msg","注销登录成功");
                        //浏览器返回json数据
                        out.write(new ObjectMapper().writeValueAsString(map));
                        out.flush();
                        out.close();
                    }
                })
                .permitAll()
                .and()
        .csrf().disable();
    }
}
           

继续阅读