springboot后端如何實現(xiàn)攜帶token登陸
實現(xiàn)思路
使用oauth2+redis+mysql來完成登陸校驗,本案例使用oauth2簡單的密碼模式來實現(xiàn)。
最終實現(xiàn)的效果為
- 登陸頁面不設置權限審核,用戶通過登陸界面登陸,輸入賬戶密碼,后端接收到賬戶密碼之后會去數(shù)據(jù)庫驗證,如果驗證通過,則返回token給前端。
- 除了登陸頁面之外,其余的頁面訪問的時候會進行權限的鑒定,如果攜帶的token對應用戶的權限不足或沒有攜帶token、攜帶了錯誤的token,不允許訪問。
- token具有時限,超時token會失效,可以通過refresh_token來刷新token的持續(xù)時間。
項目結構
項目的結構為
├─.idea │ └─dictionaries ├─log ├─src │ ├─main │ │ ├─java │ │ │ └─Rush │ │ │ ├─config │ │ │ ├─controller │ │ │ ├─mapper │ │ │ ├─pojo │ │ │ ├─service │ │ │ └─util │ │ └─resource │ └─test │ └─target
項目的重點其實也就在于config包內
config包內定義了4個類:
AuthorizationServerConfigResourceServerConfigWebSecurityConfigCORSFilter「額外針對OAuth跨域問題」
除此之外,繼承了UserDetails接口的User類,繼承UserDetailsService類的UserService類也很關鍵。
除了這6個類之外,別的類和普通mybatis項目無異
AuthorizationServerConfig
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
import org.springframework.web.bind.annotation.CrossOrigin;
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig
extends AuthorizationServerConfigurerAdapter {
@Autowired
AuthenticationManager authenticationManager;
@Autowired
RedisConnectionFactory redisConnectionFactory;
@Autowired
UserDetailsService userDetailsService;
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
public void configure(ClientDetailsServiceConfigurer clients)
throws Exception {
clients.inMemory()
.withClient("password")
.authorizedGrantTypes("password", "refresh_token")
.accessTokenValiditySeconds(1800)
.resourceIds("rid")
.scopes("all")
.secret("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints.tokenStore(new RedisTokenStore(redisConnectionFactory))
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security)
throws Exception {
security.allowFormAuthenticationForClients();
}
}
ResourceServerConfig
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.web.bind.annotation.CrossOrigin;
@Configuration
@EnableResourceServer
public class ResourceServerConfig
extends ResourceServerConfigurerAdapter {
@Override
public void configure(ResourceServerSecurityConfigurer resources)
throws Exception {
resources.resourceId("rid").stateless(true);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("admin")
.antMatchers("/user/**").hasAnyRole("user","admin")
.anyRequest().authenticated()
.and()
.formLogin()
.loginProcessingUrl("/home").permitAll()
.and()
.csrf().disable();
}
}WebSecurityConfig
import bocRush.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.web.bind.annotation.CrossOrigin;
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
? ? @Autowired
? ? UserService userService;
? ? @Bean
? ? @Override
? ? public AuthenticationManager authenticationManagerBean() throws Exception {
? ? ? ? return super.authenticationManagerBean();
? ? }
? ? @Bean
? ? @Override
? ? protected UserDetailsService userDetailsService() {
? ? ? ? return super.userDetailsService();
? ? }
? ? @Override
? ? protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// ? ? ? ?auth.inMemoryAuthentication()
// ? ? ? ? ? ? ? ?.withUser("admin")
// ? ? ? ? ? ? ? ?.password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq")
// ? ? ? ? ? ? ? ?.roles("admin")
// ? ? ? ? ? ? ? ?.and()
// ? ? ? ? ? ? ? ?.withUser("sang")
// ? ? ? ? ? ? ? ?.password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq")
// ? ? ? ? ? ? ? ?.roles("user");
? ? ? ? auth.userDetailsService(userService);
? ? }
? ? @Override
? ? protected void configure(HttpSecurity http) throws Exception {
? ? ? ? http.antMatcher("/oauth/**").authorizeRequests()
? ? ? ? ? ? ? ? .antMatchers("/oauth/**").permitAll()
? ? ? ? ? ? ? ? .and().cors()
? ? ? ? ? ? ? ? .and().csrf().disable();
? ? }
}CORSFilter
/**
?* Date ? : 2021/3/25 17:48
?* Author : nicolas
?*/
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*全局跨域配置*/
@Order(Ordered.HIGHEST_PRECEDENCE)
@Configuration
public class CORSFilter implements Filter {
? ? @Override
? ? public void init(FilterConfig filterConfig) throws ServletException {
? ? }
? ? @Override
? ? public void doFilter(ServletRequest servletRequest,
? ? ? ? ? ? ? ? ? ? ? ? ?ServletResponse servletResponse,
? ? ? ? ? ? ? ? ? ? ? ? ?FilterChain filterChain) throws IOException, ServletException {
? ? ? ? HttpServletRequest request = (HttpServletRequest) servletRequest;
? ? ? ? HttpServletResponse response = (HttpServletResponse) servletResponse;
? ? ? ? response.setHeader("Access-Control-Allow-Origin", "*");
? ? ? ? response.setHeader("Access-Control-Allow-Credentials", "true");
? ? ? ? response.setHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS,PUT,DELETE,PATCH,HEAD");
? ? ? ? response.setHeader("Access-Control-Allow-Max-Age", "3600");
? ? ? ? response.setHeader("Access-Control-Allow-Headers", "*");
? ? ? ? if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
? ? ? ? ? ? response.setStatus(HttpServletResponse.SC_OK);
? ? ? ? } else {
? ? ? ? ? ? filterChain.doFilter(servletRequest, servletResponse);
? ? ? ? }
? ? }
? ? @Override
? ? public void destroy() {
? ? }
}User
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
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 : roles) {
? ? ? ? ? ? authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getName()));
? ? ? ? }
? ? ? ? return authorities;
? ? }
? ? @Override
? ? public String getPassword() {
? ? ? ? return password;
? ? }
? ? @Override
? ? public String getUsername() {
? ? ? ? return username;
? ? }
? ? @Override
? ? public boolean isAccountNonExpired() {
? ? ? ? return true;
? ? }
? ? @Override
? ? public boolean isAccountNonLocked() {
? ? ? ? return !locked;
? ? }
? ? @Override
? ? public boolean isCredentialsNonExpired() {
? ? ? ? return true;
? ? }
? ? @Override
? ? public boolean isEnabled() {
? ? ? ? return enabled;
? ? }
? ? //省略getter/setter
? ? public Integer getId() {
? ? ? ? return id;
? ? }
? ? public void setId(Integer id) {
? ? ? ? this.id = id;
? ? }
? ? public void setUsername(String username) {
? ? ? ? this.username = username;
? ? }
? ? public void setPassword(String password) {
? ? ? ? this.password = password;
? ? }
? ? public void setEnabled(Boolean enabled) {
? ? ? ? this.enabled = enabled;
? ? }
? ? public Boolean getLocked() {
? ? ? ? return locked;
? ? }
? ? public void setLocked(Boolean locked) {
? ? ? ? this.locked = locked;
? ? }
? ? public List<Role> getRoles() {
? ? ? ? return roles;
? ? }
? ? public void setRoles(List<Role> roles) {
? ? ? ? this.roles = roles;
? ? }
}UserService
import bocRush.mapper.UserInfoMapper;
import bocRush.mapper.UserMapper;
import bocRush.pojo.User;
import bocRush.pojo.UserInfo;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
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.Service;
@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.setRoles(userMapper.getUserRolesByUid(user.getId()));
? ? ? ? //System.out.println(user.getRoles().get(1).getName() + " --- " + user.getUsername());
? ? ? ? return user;
? ? }
}對于接口的傳參數(shù)
獲取token
- 使用POST方法
http://localhost:8080/oauth/token?username=sang&password=123&grant_type=password&client_id=password&scope=all&client_secret=123
刷新token
- 使用POST方法
http://localhost:8080/oauth/token?grant_type=refresh_token&refresh_token=1a1c67a0-5f9b-49b1-9f95-dc7889c85cf5&client_id=password&client_secret=123
攜帶token訪問資源
在url內直接攜帶token
- GET方法
http://localhost:8080/user/hello?access_token=9bdde947-19b7-46fe-8fe0-0f2804150768
在header內攜帶token
- GET方法
http://localhost:8080/admin/hello
------------Header----------------
Authorization : bearer 3929d92d-f5be-4b2d-9223-8b13e2412f14
Accept : application/json
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Mybatis-Plus默認主鍵策略導致自動生成19位長度主鍵id的坑
這篇文章主要介紹了Mybatis-Plus默認主鍵策略導致自動生成19位長度主鍵id的坑,本文一步步給大家分享解決方法,給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-12-12
Java的數(shù)據(jù)類型和參數(shù)傳遞(詳解)
下面小編就為大家?guī)硪黄狫ava的數(shù)據(jù)類型和參數(shù)傳遞(詳解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-07-07
springboot vue完成編輯頁面發(fā)送接口請求功能
這篇文章主要為大家介紹了springboot+vue完成編輯頁發(fā)送接口請求功能,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-05-05
Spring中DAO被循環(huán)調用的時候數(shù)據(jù)不實時更新的解決方法
這篇文章主要介紹了Spring中DAO被循環(huán)調用的時候數(shù)據(jù)不實時更新的解決方法,需要的朋友可以參考下2014-08-08

