如何使用Spring Securiry实现前后端分离项目的登录功能 (2)

security默认提供了Basic和表单两种登录方式,不支持Json格式的数据,需要对处理登录的过滤器进行修改。这里,我们重写了UsernamePasswordAuthenticationFilter的attemptAuthentication方法。

package com.hanstrovsky.filter; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.http.MediaType; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.util.Map; /** * 自定义过滤器,重写 attemptAuthentication方法,实现使用json格式的数据进行登录 * * @author Hanstrovsky */ @Slf4j public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter { @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { if (request.getContentType().equals(MediaType.APPLICATION_JSON_UTF8_VALUE) || request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE)) { ObjectMapper mapper = new ObjectMapper(); UsernamePasswordAuthenticationToken authRequest = null; try (InputStream is = request.getInputStream()) { Map<String, String> authenticationBean = mapper.readValue(is, Map.class); String username = authenticationBean.get("username"); String password = authenticationBean.get("password"); authRequest = new UsernamePasswordAuthenticationToken( username, password); } catch (IOException e) { e.printStackTrace(); authRequest = new UsernamePasswordAuthenticationToken( "", ""); } setDetails(request, authRequest); return this.getAuthenticationManager().authenticate(authRequest); } else { // 保留原来的方法 return super.attemptAuthentication(request, response); } } } 四、实现UserDetailsService接口

这个接口是用来提供用户名和密码的,可以通过查询数据库获取用户。本例直接在代码中写死。

package com.hanstrovsky.service; import com.hanstrovsky.entity.MyUserDetails; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Repository; /** * @author Hanstrovsky */ @Repository public class MyUserDetailsService implements UserDetailsService { @Override public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException { // 可以在此处自定义从数据库查询用户 MyUserDetails myUserDetail = new MyUserDetails(); myUserDetail.setUsername(username); myUserDetail.setPassword("123456"); return myUserDetail; } } 五、实现PasswordEncoder接口

自定义密码的加密方式。

package com.hanstrovsky.util; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Component; /** * 自定义的密码加密方法,实现了PasswordEncoder接口 * * @author Hanstrovsky */ @Component public class MyPasswordEncoder implements PasswordEncoder { @Override public String encode(CharSequence charSequence) { //加密方法可以根据自己的需要修改 return charSequence.toString(); } @Override public boolean matches(CharSequence charSequence, String s) { return encode(charSequence).equals(s); } } 六、实现UserDetails接口

这个类是用来存储登录成功后的用户数据,security提供了直接获取用户信息的接口

package com.hanstrovsky.entity; import lombok.Getter; import lombok.Setter; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Component; import java.util.Collection; /** * 实现UserDetails,可自定义添加更多属性 * * @author Hanstrovsky */ @Getter @Setter @Component public class MyUserDetails implements UserDetails { //登录用户名 private String username; //登录密码 private String password; private Collection<? extends GrantedAuthority> authorities; @Override public Collection<? extends GrantedAuthority> getAuthorities() { return this.authorities; } private boolean accountNonExpired = true; private boolean accountNonLocked = true; private boolean credentialsNonExpired = true; private boolean enabled = true; }

以上,便可以实现前后端分离项目基本的登录功能。
========================================================================================

不要简单的收集学习资料,知识活在百度云或者书签列表中意义不大。

把自己困惑的地方,真正搞懂,写出来。如果别人也能看懂,那才是真的掌握了,坚持下去,应该会有收获。

========================================================================================

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wppjsj.html