初学spring security(一)

引入依赖

首先我们先导入依赖

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

 导入依赖后启动项目,会有一个默认的登录页面http://localhost:8080/login.html

 默认的username为user,password打印在控制台中。

在浏览器中输入账号和密码后会显示项目中login.html页面内容。我们可以自定义自己的登录界面账号密码,用户权限等。

自定义登录界面

实现自定义登录,主要是实现接口UserDetailsService ,返回值UserDetails是一个接口

public interface UserDetails extends Serializable{
	Collection<? extends GrantedAuthority> getAuthorities(); // 获取所有权限
	String getPassword(); //获取密码
	String getUsername(); // 获取用户名
	boolean isAccountNonExpired(); // 是否账号过期
	boolean isAccountNonLocked(); // 账号是否被锁
	boolean isCredentialsNoExpired(); // 凭证(密码)是否过期
	boolean isEnabled(); 是否可用
}

返回的User类只能用spring security自带的User类,导包注意别导错org.springframework.security.core.userdetails.User

 User的构造函数

public User(String username, String password
    ,Collection<? extends GrantedAuthority> getAuthorities){
	this(username,password,true,true,true,true,getAuthorities);
}

 getAuthorities通常都是通过AuthorityUtils.commaSeparatedStringToAuthorityList(“”)来创建authorities集合对象的。参数是一个字符串,多个权限和角色使用逗号分隔。

密码解析器

Spring Security要求容器中必须有PasswordEncoder实例。所以当自定义登录逻辑时要求必须给容器注入PaswordEncoder的bean对象

PaswordEncoder中有的方法:

encode():把参数按照特定的解析规则进行解析。

matches()验证从存储中获取的编码密码与编码后提交的原始密码是否匹配。如果密码匹配,则返回true;如果不匹配,则返回false。第一个参数表示需要被解析的密码。第二个参数表示存储的密码。

upgradeEncoding():如果解析的密码能够再次进行解析且达到更安全的结果则返回true,否则返回false。默认返回false。

 这个密码解析器实现的类有很多

通常是使用BCryptPasswordEncoder这个解析器。

下面是登录例子

先搞一个配置类,配置密码解析器 

@Configuration
public class SecurityConfig {
    @Bean
    public PasswordEncoder getPwdEncoder(){
        return new BCryptPasswordEncoder();
    }
}

实现UserDetailsService,用来实现对用户登录的操作

@Service
public class UserDetailsServiceImpl implements UserDetailsService {
    @Autowired
    private PasswordEncoder encoder;
	
	@Autowired
	private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //1. 查询数据库判断用户名是否存在,如果不存在抛出UsernameNotFoundException
		xxx.xxx.pojo.User user = userMapper.selecByUserName(username);
        if(user == null){
            throw new UsernameNotFoundException("用户名不存在");
        }
        //把查询出来的密码进行解析,或直接把password放到构造方法中。
        //理解:password就是数据库中查询出来的密码,查询出来的内容不是123
		
        String password = encoder.encode("123");
		// AuthorityUtils.commaSeparatedStringToAuthorityList("admin1,admin2,ROLE_admin3") 是加权限和角色
		UserDetails userDetails= User(user.getName(),user.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList("admin1,admin2,ROLE_admin3"));
        return userDetails;
    }
}

自定义登录页面

需要修改配置类中主要是设置哪个页面是登录页面。

配置类需要继承WebSecurityConfigurerAdapter,并重写configure方法。

只要没有认证通过,就一直会在login页面。

WebSecurityConfigurerAdapter中的一些方法参数:

successForwardUrl()登录成功后跳转地址
loginPage() 登录页面
loginProcessingUrl 登录页面表单提交地址,此地址可以不真实存在。
antMatchers():匹配内容
permitAll():允许

当进行登录时会执行UsernamePasswordAuthenticationFilter过滤器。

usernamePasrameter:账户参数名
passwordParameter:密码参数名
postOnly=true:默认情况下只允许POST请求。

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
	protected void configure(HttpSecurity http) throws Exception {
		// 表单认证
        http.formLogin()
        //当发现URL时把请求转发给自定义的登录逻辑
            .loginProcessingUrl("/login")
        // 认证成功后转发的地址。post请求(和客户端<form>)
            .successForwardUrl("/showMain")   //此处是post请求
        // 认证成功后的处理器 或者自定义类实现接口 AuthenticationSuccessHandler             
        //  .successHandle(MyAuthenticationSuccessHandler)
            .successHandle(new AuthenticationSuccessHandler(){
			    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication)IOException, ServletException{
				response.sendRedirect("/showMain")
			    }	
		    })
        // 未认证时登录页面的url地址
            .loginPage("/showLogin")
        //认证失败转发地址
            .failureForwardUrl("/showFail")     
        // 认证失败的处理器
            .failureHandler( new AuthenticationFailureHandler){
                public void onAuthenticationFailure(HttpServletRequest httpServletRequest,             HttpServletResponse httpServletResponse, Authentication authentication)IOException,     ServletException{
				response.sendRedirect("/showfail")
			    }
		    }
		// 客户端用户名参数名称
            .usernameParameter("myusername")
		// 客户端密码参数名称
             .passwordParameter("mypassword");
	}	

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

 

使用successForwardUrl()时表示成功后转发请求到地址。内部是通过successHandler()方法进行控制成功后交给哪个类进行处理

ForwardAuthenticationSuccessHandler内部就是最简单的请求转发。由于是请求转发,当遇到需要跳转到站外或在前后端分离的项目中就无法使用了。

//自定义认证成功处理器

public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

    @Override

    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {

        //Principal 主体,存放了登录用户的信息

        User user = (User)authentication.getPrincipal();

        System.out.println(user.getUsername());

        System.out.println(user.getPassword());//密码输出为null

        System.out.println(user.getAuthorities());

        //重定向到百度。这只是一个示例,具体需要看项目业务需求

        httpServletResponse.sendRedirect("http://www.baidu.com");

    }

}

失败跟成功一样的

//自定义认证失败处理器

public class MyForwardAuthenticationFailureHandler implements AuthenticationFailureHandler {

    @Override
    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {

        httpServletResponse.sendRedirect("/showfail.html");
    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值