开发者

springboot后端如何实现携带token登陆

开发者 https://www.devze.com 2022-11-28 14:07 出处:网络 作者: nian002
目录实现思路最终实现的效果为项目结构项目的结构为对于接口的传参数获取token刷新token携带token访问资源实现思路使用oauth2+redis+mysql来完成登陆校验,本案例使用oauth2...
目录
  • 实现思路
    • 最终实现的效果为
  • 项目结构
    • 项目的结构为
  • 对于接口的传参数
    • 获取token
    • 刷新token
    • 携带token访问资源

实现思路

使用oauth2+Redis+mysql来完成登陆校验,本案例使用oauth2简单的密码模式来实现。

最终实现的效果为

  • 登陆页面不设置权限审核,用户通过登陆界面登陆,输入账户密码,后端接收到账户密码之后会去数据库验证,如果验证通过,则返回token给前端。
  • 除了登陆页面之外,其余的页面访问的时候会进行权限的鉴定,如果携带的token对应用户的权限不足或没有携带token、携带了错误的token,不允许访问。
  • token具有时限,超时token会失效,可以通过refresh_token来刷新token的持续时间。

项目结构

项目的结构为

├─.idea
│  └─dictionaries
├─log
├─src
│  ├─main
│  │  ├─Java
│  │  │  └─Rush
│  │  │      ├─config
│  │  │      ├─controller
│  │  │      ├─mapper
│  │  │      ├─pojo
│  │  │      ├─service
│  │  │      └─util
│  │  └─resource
│  └─test
│
└─target

项目的重点其实也就在于config包内

config包内定义了4个类:

  • AuthorizationServerConfig
  • ResourceServerConfig
  • WebSecurityConfig
  • CORSFilter「额外针对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(AuthorizationServerEndpointsConf编程igurer 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.AuthenticationManagerphp;
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.setHead开发者_JS教程er("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;
  }
}

对于接口的传参数

获取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

python
  • GET方法

http://localhost:8080/admin/hello

------------Header----------------

Authorization : bearer 3929d92d-f5be-4b2d-9223-8b13e2412f14

Accept : application/json

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号