快速上手spring-boot+spring-security+jwt

这篇博客介绍了如何快速上手使用Spring Boot、Spring Security和JWT进行安全认证。内容涵盖了数据库表设计,包括用户、角色和用户角色表,实体类的创建,特别是实现了UserDetails的用户类,以及安全配置和JWT token的处理,特别是使用过滤器进行token验证的流程。
摘要由CSDN通过智能技术生成

快速上手spring-boot+spring-security+jwt

数据库表设计

三张表:

  • 用户表 user

  • 角色表 role

  • 用户角色表 user_roles

图示:

图1.png

实体类

用户类


@Entity
public class User implements UserDetails {

    @Id
    @GeneratedValue
    private Long id;

    private String username;

    private String password;

    // 角色
    @ManyToMany(cascade = {CascadeType.REFRESH},fetch = FetchType.EAGER)
    private List<Role> roles;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public List<Role> getRoles() {
        return roles;
    }

    public void setRoles(List<Role> roles) {
        this.roles = roles;
    }
    
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<GrantedAuthority> authorities = new ArrayList<>();
        for (Role role : roles) {
            authorities.add( new SimpleGrantedAuthority( role.getName() ) );
        }
        return authorities;
    }

    @Override
    public String getUsername() {
        retu
Spring Boot Security OAuth2 JWT 单点登录是一个非常实用的功能。下面是一个完整的示例,帮助你快速上手。 首先,我们需要在 pom.xml 文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.security.oauth.boot</groupId> <artifactId>spring-security-oauth2-autoconfigure</artifactId> <version>2.1.0.RELEASE</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>0.10.7</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-impl</artifactId> <version>0.10.7</version> <scope>runtime</scope> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-jackson</artifactId> <version>0.10.7</version> <scope>runtime</scope> </dependency> ``` 然后,我们需要创建一个名为 `SecurityConfig` 的类,继承 `WebSecurityConfigurerAdapter` 类,并重写 `configure` 方法。在这个方法中,我们可以配置 Spring Security 的一些基本设置,如登录页面、用户认证等。 ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private CustomUserDetailsService userDetailsService; @Autowired private CustomOAuth2UserService oAuth2UserService; @Autowired private OAuth2AuthenticationSuccessHandler oAuth2AuthenticationSuccessHandler; @Autowired private OAuth2AuthenticationFailureHandler oAuth2AuthenticationFailureHandler; @Autowired private HttpCookieOAuth2AuthorizationRequestRepository httpCookieOAuth2AuthorizationRequestRepository; @Override protected void configure(HttpSecurity http) throws Exception { http .cors() .and() .csrf() .disable() .formLogin() .disable() .httpBasic() .disable() .exceptionHandling() .authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)) .and() .authorizeRequests() .antMatchers("/", "/error", "/webjars/**").permitAll() .antMatchers("/oauth2/**").permitAll() .anyRequest().authenticated() .and() .oauth2Login() .authorizationEndpoint() .baseUri("/oauth2/authorize") .authorizationRequestRepository(cookieAuthorizationRequestRepository()) .and() .redirectionEndpoint() .baseUri("/oauth2/callback/*") .and() .userInfoEndpoint() .userService(oAuth2UserService) .and() .successHandler(oAuth2AuthenticationSuccessHandler) .failureHandler(oAuth2AuthenticationFailureHandler); } @Bean public HttpCookieOAuth2AuthorizationRequestRepository cookieAuthorizationRequestRepository() { return new HttpCookieOAuth2AuthorizationRequestRepository(); } @Bean public JwtEncoder jwtEncoder() { return new JwtEncoder(); } @Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/resources/**"); } @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Autowired public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(encoder()); } @Bean public PasswordEncoder encoder() { return new BCryptPasswordEncoder(); } } ``` 接下来,我们需要创建一个名为 `CustomUserDetailsService` 的类,实现 `UserDetailsService` 接口,并重写 `loadUserByUsername` 方法。在这个方法中,我们可以实现自己的用户认证逻辑。 ```java @Service public class CustomUserDetailsService implements UserDetailsService { @Autowired private UserRepository userRepository; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userRepository.findByUsername(username) .orElseThrow(() -> new UsernameNotFoundException("User not found with username : " + username)); return UserPrincipal.create(user); } @Transactional public UserDetails loadUserById(Long id) { User user = userRepository.findById(id).orElseThrow( () -> new ResourceNotFoundException("User", "id", id) ); return UserPrincipal.create(user); } } ``` 然后,我们需要创建一个名为 `CustomOAuth2UserService` 的类,实现 `OAuth2UserService` 接口,并重写 `loadUser` 方法。在这个方法中,我们可以实现自己的第三方登录逻辑,比如从 Facebook 或 Google 获取用户信息。 ```java @Service public class CustomOAuth2UserService extends DefaultOAuth2UserService { @Autowired private UserRepository userRepository; @Override public OAuth2User loadUser(OAuth2UserRequest oAuth2UserRequest) throws OAuth2AuthenticationException { OAuth2User oAuth2User = super.loadUser(oAuth2UserRequest); try { return processOAuth2User(oAuth2UserRequest, oAuth2User); } catch (Exception ex) { throw new OAuth2AuthenticationException(ex.getMessage(), ex); } } private OAuth2User processOAuth2User(OAuth2UserRequest oAuth2UserRequest, OAuth2User oAuth2User) { OAuth2UserInfo oAuth2UserInfo = OAuth2UserInfoFactory.getOAuth2UserInfo( oAuth2UserRequest.getClientRegistration().getRegistrationId(), oAuth2User.getAttributes() ); if(StringUtils.isEmpty(oAuth2UserInfo.getEmail())) { throw new OAuth2AuthenticationProcessingException("Email not found from OAuth2 provider"); } Optional<User> userOptional = userRepository.findByEmail(oAuth2UserInfo.getEmail()); User user; if(userOptional.isPresent()) { user = userOptional.get(); if(!user.getProvider().equals(AuthProvider.valueOf(oAuth2UserRequest.getClientRegistration().getRegistrationId()))) { throw new OAuth2AuthenticationProcessingException("Looks like you're signed up with " + user.getProvider() + " account. Please use your " + user.getProvider() + " account to login."); } user = updateExistingUser(user, oAuth2UserInfo); } else { user = registerNewUser(oAuth2UserRequest, oAuth2UserInfo); } return UserPrincipal.create(user, oAuth2User.getAttributes()); } private User registerNewUser(OAuth2UserRequest oAuth2UserRequest, OAuth2UserInfo oAuth2UserInfo) { User user = new User(); user.setProvider(AuthProvider.valueOf(oAuth2UserRequest.getClientRegistration().getRegistrationId())); user.setProviderId(oAuth2UserInfo.getId()); user.setUsername(oAuth2UserInfo.getName()); user.setEmail(oAuth2UserInfo.getEmail()); user.setImageUrl(oAuth2UserInfo.getImageUrl()); return userRepository.save(user); } private User updateExistingUser(User existingUser, OAuth2UserInfo oAuth2UserInfo) { existingUser.setUsername(oAuth2UserInfo.getName()); existingUser.setImageUrl(oAuth2UserInfo.getImageUrl()); return userRepository.save(existingUser); } } ``` 接着,我们需要创建一个名为 `OAuth2UserInfo` 的接口,定义一些获取第三方登录用户信息的方法。 ```java public interface OAuth2UserInfo { String getId(); String getName(); String getEmail(); String getImageUrl(); } ``` 然后,我们需要创建一个名为 `OAuth2UserInfoFactory` 的工厂类,根据不同的第三方登录平台,返回不同的实现类。 ```java public class OAuth2UserInfoFactory { public static OAuth2UserInfo getOAuth2UserInfo(String registrationId, Map<String, Object> attributes) { if(registrationId.equalsIgnoreCase(AuthProvider.google.toString())) { return new GoogleOAuth2UserInfo(attributes); } else if (registrationId.equalsIgnoreCase(AuthProvider.facebook.toString())) { return new FacebookOAuth2UserInfo(attributes); } else { throw new OAuth2AuthenticationProcessingException("Sorry! Login with " + registrationId + " is not supported yet."); } } } ``` 最后,我们需要创建一个名为 `JwtEncoder` 的类,实现 `TokenEnhancer` 接口,并重写 `enhance` 方法。在这个方法中,我们可以创建一个 JWT Token,并将用户信息存储在 Token 中。 ```java public class JwtEncoder implements TokenEnhancer { @Override public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { User user = (User) authentication.getPrincipal(); Map<String, Object> additionalInfo = new HashMap<>(); additionalInfo.put("id", user.getId()); additionalInfo.put("username", user.getUsername()); ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo); return accessToken; } } ``` 至此,我们的 Spring Boot Security OAuth2 JWT 单点登录示例就完成了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值