Ajax 로그인 요청을 처리하는 SpringBoot 및 SpringSecurity 관련 문제

不言
풀어 주다: 2018-06-25 10:31:17
원래의
1703명이 탐색했습니다.

이 글은 Ajax 로그인 요청을 처리하는 SpringBoot+SpringSecurity의 문제를 주로 소개하고 있으며, 도움이 필요한 친구들이 참고할 수 있습니다.

최근 프로젝트에서 프론트와 스프링의 분리라는 문제를 겪었습니다. 백엔드, 프런트 엔드는 Vue로 수행되고 모든 데이터 요청은 vue-resource를 사용하여 이루어지며 양식은 사용되지 않으므로 데이터 상호 작용은 모두 JSON을 사용하여 수행되고 Spring Boot는 백그라운드에서 사용되며 Spring Security가 사용됩니다. 권한 확인을 위해 이전에는 Spring Security를 ​​사용하여 페이지를 처리했습니다. 네, 이번에는 단순히 Ajax 요청을 처리하므로 발생한 몇 가지 문제를 기록하겠습니다. 여기의 솔루션은 Ajax 요청에 적합할 뿐만 아니라 모바일 요청 확인 문제도 해결합니다.

프로젝트 만들기

먼저 Spring Boot 프로젝트를 만들어야 합니다. 생성할 때 Web, Spring Security, MySQL 및 MyBatis를 도입해야 합니다(데이터베이스 프레임워크는 실제로 선택 사항입니다. 여기서는 MyBatis를 사용합니다). 생성 후 종속성 파일은 다음과 같습니다.

<dependency>
 <groupId>org.mybatis.spring.boot</groupId>
 <artifactId>mybatis-spring-boot-starter</artifactId>
 <version>1.3.1</version>
</dependency>
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 <scope>runtime</scope>
</dependency>
<dependency>
 <groupId>commons-codec</groupId>
 <artifactId>commons-codec</artifactId>
 <version>1.11</version>
</dependency>
로그인 후 복사

마지막 commons-codec 종속성은 제가 수동으로 추가했습니다. 이것은 MD5 메시지 다이제스트를 생성하는 데 사용할 수 있는 Apache 오픈 소스 프로젝트입니다. 다음 기사에서는 비밀번호에 대해 간략하게 분석하겠습니다.

데이터베이스 생성 및 구성

로직을 단순화하기 위해 여기에 다음과 같이 사용자 테이블, 역할 테이블, 사용자 역할 연관 테이블이라는 세 개의 테이블을 만들었습니다.

다음으로 애플리케이션을 추가해야 합니다. 여기서는 특정 상황에 따라 .properties에서 데이터베이스를 구성할 수 있습니다.

spring.datasource.url=jdbc:mysql:///vueblog
spring.datasource.username=root
spring.datasource.password=123
로그인 후 복사

엔티티 클래스 구성

이것은 주로 사용자 클래스 구성을 의미하며 다음과 같이 UserDetails 인터페이스를 구현해야 합니다.

public class User implements UserDetails {
 private Long id;
 private String username;
 private String password;
 private String nickname;
 private boolean enabled;
 private List<Role> roles;
 @Override
 public boolean isAccountNonExpired() {
 return true;
 }
 @Override
 public boolean isAccountNonLocked() {
 return true;
 }
 @Override
 public boolean isCredentialsNonExpired() {
 return true;
 }
 @Override
 public boolean isEnabled() {
 return enabled;
 }
 @Override
 public List<GrantedAuthority> getAuthorities() {
 List<GrantedAuthority> authorities = new ArrayList<>();
 for (Role role : roles) {
  authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getName()));
 }
 return authorities;
 }
 //getter/setter省略...
}
로그인 후 복사

구현한 후 UserDetails 인터페이스에는 구현해야 하는 여러 메서드가 있습니다. Boolean을 반환하는 네 가지 메서드는 모두 이름으로 잘 알려져 있습니다. 활성화는 이 필드가 내 데이터베이스에 활성화되어 있는지 여부를 나타냅니다. 쿼리 결과에 따라 반환됩니다. 단순 기간 동안에는 true가 직접 반환됩니다. getAuthorities 메서드는 실제로 역할의 데이터를 List< GrantedAuthority> 여기서 주의할 점이 있습니다. 데이터베이스에 저장하는 역할 이름은 모두 '최고 관리자', '일반 사용자' 등이므로 ROLE_ 这样的字符开始的,因此需要在这里手动加上 ROLE_로 시작하지 않습니다.

역할 엔터티 클래스도 있는데, 이는 비교적 간단하고 데이터베이스 필드에 따라 생성될 수 있습니다. 여기서는 자세히 설명하지 않겠습니다.

Create UserService

여기의 UserService도 매우 특별하며 다음과 같이 UserDetailsService 인터페이스를 구현해야 합니다. 인터페이스, 즉 사용자 이름 쿼리 사용자에 따라. MyBatis의 두 개의 Mapper가 여기에 삽입되며, UserMapper는 사용자를 쿼리하는 데 사용되고 RolesMapper는 역할을 쿼리하는 데 사용됩니다. loadUserByUsername 메소드에서는 먼저 들어오는 매개변수(매개변수는 사용자가 로그인할 때 입력한 사용자 이름)를 기반으로 사용자를 쿼리합니다. 발견된 사용자가 null인 경우 UsernameNotFoundException 예외를 직접 발생시킬 수 있지만 처리의 편의를 위해 , 아무 값 없이 A User 객체를 반환하여 후속 비밀번호 비교 프로세스 중에 로그인 실패가 계속 발견되도록 했습니다. (현재 발견된 사용자가 null이 아닌 경우에는 비즈니스 요구에 따라 조정할 수 있습니다.) 그런 다음 사용자 ID로 사용자의 역할을 쿼리하고 쿼리 결과를 사용자 개체에 넣습니다. 이 쿼리 결과는 사용자 개체의 getAuthorities 메서드에 사용됩니다.

보안 구성

먼저 보안 구성을 살펴보고 하나씩 설명하겠습니다.

@Service
public class UserService implements UserDetailsService {
 @Autowired
 UserMapper userMapper;
 @Autowired
 RolesMapper rolesMapper;
 @Override
 public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
  User user = userMapper.loadUserByUsername(s);
  if (user == null) {
   //避免返回null,这里返回一个不含有任何值的User对象,在后期的密码比对过程中一样会验证失败
   return new User();
  }
  //查询用户的角色信息,并返回存入user中
  List<Role> roles = rolesMapper.getRolesByUid(user.getId());
  user.setRoles(roles);
  return user;
 }
}
로그인 후 복사

이것이 우리 구성의 핵심입니다. 친구 여러분, 내 말을 들어보세요. one by one :

1 우선 구성 클래스이므로 @Configuration 주석을 추가해야 하며, Spring Security의 구성이므로 WebSecurityConfigurerAdapter를 상속해야 한다는 점을 기억하세요.

2. 방금 생성한 UserService를 삽입합니다. 나중에 사용하겠습니다.

3.configure(AuthenticationManagerBuilder auth)方法中用来配置我们的认证方式,在auth.userDetailsService()方法中传入userService,这样userService中的loadUserByUsername方法在用户登录时将会被自动调用。后面的passwordEncoder是可选项,可写可不写,因为我是将用户的明文密码生成了MD5消息摘要后存入数据库的,因此在登录时也需要对明文密码进行处理,所以就加上了passwordEncoder,加上passwordEncoder后,直接new一个PasswordEncoder匿名内部类即可,这里有两个方法要实现,看名字就知道方法的含义,第一个方法encode显然是对明文进行加密,这里我使用了MD5消息摘要,具体的实现方法是由commons-codec依赖提供的;第二个方法matches是密码的比对,两个参数,第一个参数是明文密码,第二个是密文,这里只需要对明文加密后和密文比较即可(小伙伴如果对此感兴趣可以继续考虑密码加盐)。

4.configure(HttpSecurity http)用来配置我们的认证规则等,authorizeRequests方法表示开启了认证规则配置,antMatchers("/admin/**").hasRole("超级管理员")表示 /admin/** 的路径需要有‘超级管理员'角色的用户才能访问,我在网上看到小伙伴对hasRole方法中要不要加 ROLE_ 前缀有疑问,这里是不要加的,如果用hasAuthority方法才需要加。anyRequest().authenticated()表示其他所有路径都是需要认证/登录后才能访问。接下来我们配置了登录页面为login_page,登录处理路径为/login,登录用户名为username,密码为password,并配置了这些路径都可以直接访问,注销登陆也可以直接访问,最后关闭csrf。在successHandler中,使用response返回登录成功的json即可,切记不可以使用defaultSuccessUrl,defaultSuccessUrl是只登录成功后重定向的页面,使用failureHandler也是由于相同的原因。

5.configure(WebSecurity web)方法中我配置了一些过滤规则,不赘述。

6.另外,对于静态文件,如 /images/**/css/**/js/** 这些路径,这里默认都是不拦截的。

Controller

最后来看看我们的Controller,如下:

@RestController
public class LoginRegController {

 /**
  * 如果自动跳转到这个页面,说明用户未登录,返回相应的提示即可
  * <p>
  * 如果要支持表单登录,可以在这个方法中判断请求的类型,进而决定返回JSON还是HTML页面
  *
  * @return
  */
 @RequestMapping("/login_page")
 public RespBean loginPage() {
  return new RespBean("error", "尚未登录,请登录!");
 }
}
로그인 후 복사

这个Controller整体来说还是比较简单的,RespBean一个响应bean,返回一段简单的json,不赘述,这里需要小伙伴注意的是 login_page ,我们配置的登录页面是一个 login_page ,但实际上 login_page 并不是一个页面,而是返回一段JSON,这是因为当我未登录就去访问其他页面时Spring Security会自动跳转到到 login_page 页面,但是在Ajax请求中,不需要这种跳转,我要的只是是否登录的提示,所以这里返回json即可。

测试

最后小伙伴可以使用POSTMAN或者RESTClient等工具来测试登录和权限问题,我就不演示了。

Ok,经过上文的介绍,想必小伙伴们对Spring Boot+Spring Security处理Ajax登录请求已经有所了解了,好了,本文就说到这里,有问题欢迎留言讨论

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

在Angular4中输入属性与输出属性(详细教程)

在JS中如何实现ajax和同源策略

在JS中如何实现ajax与ajax的跨域请求

위 내용은 Ajax 로그인 요청을 처리하는 SpringBoot 및 SpringSecurity 관련 문제의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!