温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Java在SpringBoot中的用户认证授权方法

发布时间:2024-11-28 09:23:29 来源:亿速云 阅读:82 作者:小樊 栏目:编程语言

在Spring Boot中,用户认证和授权可以通过多种方式实现,包括基于表单登录、OAuth2、JWT等。下面是一些常用的方法:

  1. 基于表单登录的用户认证

在Spring Boot中,可以使用Spring Security框架实现基于表单登录的用户认证。首先,需要在项目中引入Spring Security依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

接下来,需要配置Spring Security。在项目中创建一个名为SecurityConfig的类,继承WebSecurityConfigurerAdapter,并重写configure方法:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/public/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .permitAll();
    }
}

在这个例子中,我们配置了允许对/public/**的访问不需要认证,其他请求需要认证。同时,我们配置了一个基于表单的登录页面/login

接下来,需要实现UserDetailsService接口,用于加载用户信息。在项目中创建一个名为UserDetailsServiceImpl的类,实现UserDetailsService接口:

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("User not found");
        }
        return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), new ArrayList<>());
    }
}

在这个例子中,我们从数据库中加载用户信息,并返回一个UserDetails对象。

最后,需要在项目中创建一个登录页面/login,并在表单中输入用户名和密码。当用户提交表单时,Spring Security会自动进行认证。

  1. OAuth2认证

Spring Security还支持OAuth2认证,可以通过配置授权服务器来实现。首先,需要在项目中引入Spring Security OAuth2依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security-oauth2</artifactId>
</dependency>

接下来,需要配置授权服务器。在项目中创建一个名为AuthorizationServerConfig的类,继承AuthorizationServerConfigurerAdapter,并重写configure方法:

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
            .withClient("client")
            .secret("{noop}secret")
            .authorizedGrantTypes("password", "refresh_token")
            .scopes("read", "write")
            .accessTokenValiditySeconds(3600)
            .refreshTokenValiditySeconds(2592000);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager);
    }
}

在这个例子中,我们配置了一个内存中的客户端,并设置了授权类型、作用域和有效期等参数。

接下来,需要配置资源服务器。在项目中创建一个名为ResourceServerConfig的类,继承ResourceServerConfigurerAdapter,并重写configure方法:

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/api/**").authenticated();
    }
}

在这个例子中,我们配置了允许对/api/**的访问需要认证。

最后,需要在项目中创建一个受保护的API资源,例如/api/users。当用户尝试访问这个资源时,需要先进行OAuth2认证。

  1. JWT认证

JWT(JSON Web Token)是一种用于双方之间传递安全信息的开放标准。在Spring Boot中,可以使用jjwt库实现JWT认证。首先,需要在项目中引入jjwt依赖:

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.11.2</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.11.2</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.11.2</version>
    <scope>runtime</scope>
</dependency>

接下来,需要实现JWT认证。在项目中创建一个名为JwtAuthenticationFilter的类,继承OncePerRequestFilter,并重写doFilter方法:

public class JwtAuthenticationFilter extends OncePerRequestFilter {

    @Autowired
    private JwtUserDetailsService jwtUserDetailsService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        final String requestTokenHeader = request.getHeader("Authorization");

        String username = null;
        String jwtToken = null;
        // JWT Token is in the form "Bearer token". Remove Bearer word and get
        // only the Token
        if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
            jwtToken = requestTokenHeader.substring(7);
            try {
                username = jwtTokenUtil.getUsernameFromToken(jwtToken);
            } catch (IllegalArgumentException e) {
                System.out.println("Unable to get JWT Token");
            } catch (ExpiredJwtException e) {
                System.out.println("JWT Token has expired");
            }
        } else {
            logger.warn("JWT Token does not begin with Bearer String");
        }

        //.. more code to set username and jwtToken if needed

        filterChain.doFilter(request, response);
    }
}

在这个例子中,我们从请求头中获取JWT令牌,并尝试从中提取用户名。如果令牌有效,我们将用户名和令牌传递给过滤器链的下一个过滤器。

接下来,需要实现JwtUserDetailsService接口,用于加载用户信息。在项目中创建一个名为JwtUserDetailsServiceImpl的类,实现JwtUserDetailsService接口:

@Service
public class JwtUserDetailsServiceImpl implements JwtUserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public JwtUserDetails loadUserByUsername(String username) {
        User user = userRepository.findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("User not found");
        }
        return new JwtUserDetails(user);
    }
}

在这个例子中,我们从数据库中加载用户信息,并返回一个JwtUserDetails对象。

最后,需要在项目中创建一个过滤器,将JwtAuthenticationFilter添加到过滤器链中。在项目中创建一个名为WebSecurityConfig的类,继承WebSecurityConfigurerAdapter,并重写configure方法:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtAuthenticationFilter jwtAuthenticationFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/public/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
    }
}

在这个例子中,我们将JwtAuthenticationFilter添加到过滤器链中,使其在用户名密码认证过滤器之前执行。

现在,当用户尝试访问受保护的资源时,需要进行JWT认证。用户需要在请求头中添加一个包含JWT令牌的Authorization字段。例如,可以使用以下代码生成一个JWT令牌:

public String generateToken(String username) {
    Map<String, Object> claims = new HashMap<>();
    return Jwts.builder()
            .setClaims(claims)
            .setSubject(username)
            .setIssuedAt(new Date(System.currentTimeMillis()))
            .setExpiration(new Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY * 1000))
            .signWith(SignatureAlgorithm.HS512, SECRET)
            .compact();
}

在这个例子中,我们生成一个包含用户名、签发时间和过期时间的JWT令牌。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI