Spring Security实现登陆以及权限认证

举报
多米诺的古牌 发表于 2022/07/23 23:32:54 2022/07/23
【摘要】 1.Spring Security是怎么鉴权和实现权限认证的呢? 一般我们会创建一个Spring Security的配置来进行权限的认证设置、各种拦截策略以及各种自定义的配置。

1.Spring Security是怎么鉴权和实现权限认证的呢?

一般我们会创建一个Spring Security的配置来进行权限的认证设置、各种拦截策略以及各种自定义的配置。

1.1 创建Spring Security配置类

只要继承了WebSecurityConfigurerAdapter抽象类并且加上Spring的配置注解@Configuration以及将Bean放到容器中管理的 @EnableWebSecurity注解和@EnableGlobalMethodSecurity(prePostEnabled=true)就可以完成一个Spring Security的配置类的创建,实现全局生效自定义的安全配置。在创建完成后,可以重载里面很多设置配置的方法,如下图所示:

1.2 其中有很多public void configure这个的重载方法,用于配置不同的拦截策略。

用于根据系统自定义一些拦截策略,provider就实现了AuthenticationProvider接口的自定义配置处理类

1.2.1 下面这种AuthenticationManagerBuilder auth参数的是身份验证提供程序是需要自定义配置的。

@Override public void configure(AuthenticationManagerBuilder auth) throws Exception { 
   auth.authenticationProvider(provider); 
}

provider是实现了AuthenticationProvider接口的自定义配置处理类,provider自定义类中实现方法public Authentication authenticate(Authentication authentication)中可以设置一些自定义的属性值,也可以从authentication参数中获取登录的用户名和密码。

@Override 
public Authentication authenticate(Authentication authentication) throws AuthenticationException {   
       CustomWebAuthenticationDetails details = (CustomWebAuthenticationDetails) authentication.getDetails();
       String username = authentication.getName(); 
       String password = (String) authentication.getCredentials();
       String imgCode = details.getImgCode();
       ... ...
}

如果想要配置一些别的参数比如验证码可以通过继承WebAuthenticationDetails类设置自定义的一些属性,可以从请求参数中获取到这些参数,再在上面的安全拦截的配置类中强转为这个自定义的类从中就可以获取我们需要设置的自定义的安全配置了。

//比如可以配置验证码
public class CustomWebAuthenticationDetails extends WebAuthenticationDetails {    
   private final String imgCode;     
   public CustomWebAuthenticationDetails(HttpServletRequest request) {
       super(request);      
       imgCode = request.getParameter("imgCode");    
   }     
   public String getImgCode() {       return imgCode;    }  
}

还有一种配置是下面这样的,可以设置内存指定的登录的账号密码,指定角色,不加.passwordEncoder(new MyPasswordEncoder())或者注入该类的Bean就不是以明文的方式进行匹配,会报错,如果加上就需要配置自己myUserService跟数据库配置自定义查询,然后配置自定义的加密解密的配置类MyPasswordEncoder,实现不明文传输 。

@Override
 protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
     auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN"); 
    auth.inMemoryAuthentication().withUser("demo").password("demo").roles("ADMIN"); 
    auth.inMemoryAuthentication().withUser("testRole").password("testRole").roles("AD");
     auth.userDetailsService(myUserService).passwordEncoder(new MyPasswordEncoder());
  }
其中myUserService是配置自定义的数据库配置
@Component
 public class MyUserService implements UserDetailsService{
     @Override
     public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
         return null;
     }
 }
其中new MyPasswordEncoder()可以配置加密
@Component
 public class MyPasswordEncoder implements PasswordEncoder { 
    @Override
     public String encode(CharSequence charSequence) {
         return charSequence.toString();
     }
      @Override
     public boolean matches(CharSequence charSequence, String s) {
         return s.equals(charSequence.toString()); 
    } 
//private final static String SALT = "这个是自定义的salt";

  //    @Override 
//    public String encode(CharSequence charSequence) { //
 //        return MD5Util.MD5Encode(charSequence.toString(),SALT); //    } // 
//    @Override 
//    public boolean matches(CharSequence rawPassword, String encodedPassword) { //
 //        return MD5Util.isPasswordValid(encodedPassword,rawPassword.toString(),SALT); //    }
 }

1.2.2 参数是HttpSecurity http的是主要的接口请求拦截配置

这里就是主要的安全拦截配置了,可以在其中配置登录相关的处理,成功和失败的相关响应,配置登录和登出接口的定义(这里配置后可以不用在控制器中再配置相关接口,只需要在拦截器中配置好相关的安全参数的拦截策略就可以,在访问配置登录接口时,会自动进入到自定义的拦截器中进行参数判断)。还有很多其他配置,目前还在探索中。。。

 @Override
protected void configure(HttpSecurity http) throws Exception {
		http
				// 关闭csrf防护
				.csrf().disable().headers().frameOptions().disable().and();
		http
				// 登录处理
				.formLogin().authenticationDetailsSource(authenticationDetailsSource)
				// 自定义登陆接受参数名
				.usernameParameter("username").passwordParameter("password")
				// 定义登录页面
				.loginPage("/login")
				// 登录处理接口
				.loginProcessingUrl("/admin/login")
				// 登录成功后处理
				.successHandler(new AuthenticationSuccessHandler() {
					@Override
					public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
							Authentication authentication) throws IOException, ServletException {
						response.setContentType("application/json;charset=utf-8");
						PrintWriter writer = response.getWriter();
						writer.append("{\"code\": 0,\"msg\": \"ok\"}");
						writer.flush();
						writer.close();
					}
				})
				// 登录失败后处理
				.failureHandler(new AuthenticationFailureHandler() {
					@Override
					public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
							AuthenticationException exception) throws IOException, ServletException {
						String writerStr = "{\"code\": 1,\"msg\": \"error\"}";
						if (exception instanceof MyException) {
							MyException e = (MyException) exception;
							RespModel resp = new RespModel(e.getCode(), e.getMsg());
							writerStr = JSON.toJSONString(resp);
						}
						response.setContentType("application/json;charset=utf-8");
						PrintWriter writer = response.getWriter();
						writer.append(writerStr);
						writer.flush();
						writer.close();
					}
				}).permitAll().and()
				// 退出登录
				.logout().logoutUrl("/logout").permitAll();
		http.authorizeRequests().anyRequest().authenticated().and();
		// Session的并发控制,这里设为最多一个,只允许一个用户登录,如果同一个账户两次登录,那么第一个账户将被踢下线
		http.sessionManagement().maximumSessions(1).expiredUrl("/login");//自己实现的userDetail要重写EqualsAndHashCode 注解:@EqualsAndHashCode(callSuper = true)
		// 当一个用户已经认证过了,在另外一个地方重新进行登录认证,spring security可以阻止其再次登录认证,从而保持原来的会话可用性
		// 存在一个问题,当用户登陆后,没有退出直接关闭浏览器,则再次打开浏览器时,此时浏览器的session若被删除的话,用户只能等到服务器的session过期后,才能再次登录。
	    //http.sessionManagement().maximumSessions(1).maxSessionsPreventsLogin(true);
}

1.2.3 参数是WebSecurity web是配置静态资源

可以设置忽略拦截静态资源的路径等一些配置。

@Override 
public void configure(WebSecurity web) throws Exception { 
    web.ignoring().antMatchers("/js/**", "/css/**", "/img/**", "/html/**", "/error");
 }

以上就是目前探索的一些Spring Secrity的一些安全认证和鉴权策略的实现配置方法,继续探索ing...

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。