黑狐家游戏

单点登录实现方案java,单点登录前端实现代码

欧气 1 0

单点登录前端实现代码

一、引言

单点登录(Single Sign-On,SSO)是一种身份验证机制,允许用户使用一组凭证(通常是用户名和密码)登录到多个相关的应用程序或系统,而无需在每个应用程序中分别输入凭证,单点登录的目的是提高用户体验,减少用户的记忆负担,并提高安全性。

我们将介绍如何使用 Java 实现单点登录,并提供相应的前端代码示例,我们将使用 Spring Security 框架来实现单点登录,并使用 JWT(JSON Web Token)来管理用户的会话。

二、单点登录实现方案

1、用户认证:用户首先需要在身份验证服务中进行认证,身份验证服务将验证用户的凭证,并生成一个 JWT 令牌。

2、令牌存储:生成的 JWT 令牌将被存储在用户的浏览器中,令牌将包含用户的身份信息和会话信息。

3、单点登录:当用户访问其他需要单点登录的应用程序时,应用程序将首先检查用户的浏览器中是否存在有效的 JWT 令牌,如果令牌存在且有效,应用程序将使用令牌中的身份信息来验证用户的身份,并允许用户访问应用程序。

4、令牌刷新:为了保持用户的会话活跃,令牌将定期刷新,当令牌即将过期时,应用程序将向身份验证服务发送一个请求,以刷新令牌,身份验证服务将验证令牌的有效性,并生成一个新的令牌。

5、令牌过期:如果令牌过期,用户将需要重新进行认证,身份验证服务将要求用户输入新的凭证,并生成一个新的令牌。

三、Java 实现单点登录

1、创建身份验证服务:我们将使用 Spring Boot 框架来创建身份验证服务,我们需要创建一个 Maven 项目,并添加以下依赖项:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

我们需要创建一个User 实体类,用于表示用户的信息:

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String username;
    private String password;
    // 省略 getter 和 setter 方法
}

我们需要创建一个UserRepository 接口,用于与数据库进行交互:

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    User findByUsername(String username);
}

我们需要创建一个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 UserDetails() {
            @Override
            public Collection<? extends GrantedAuthority> getAuthorities() {
                return AuthorityUtils.NO_AUTHORITIES;
            }
            @Override
            public String getPassword() {
                return user.getPassword();
            }
            @Override
            public String getUsername() {
                return user.getUsername();
            }
            @Override
            public boolean isAccountNonExpired() {
                return true;
            }
            @Override
            public boolean isAccountNonLocked() {
                return true;
            }
            @Override
            public boolean isCredentialsNonExpired() {
                return true;
            }
            @Override
            public boolean isEnabled() {
                return true;
            }
        };
    }
}

我们需要创建一个AuthenticationProvider 实现类,用于处理用户的认证请求:

@Service
public class JwtAuthenticationProvider implements AuthenticationProvider {
    @Autowired
    private UserDetailsService userDetailsService;
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String username = authentication.getName();
        String password = authentication.getCredentials().toString();
        UserDetails userDetails = userDetailsService.loadUserByUsername(username);
        if (!password.equals(userDetails.getPassword())) {
            throw new BadCredentialsException("Invalid username or password");
        }
        Jwt jwt = new Jwt();
        jwt.setSubject(username);
        jwt.setExpiration(new Date(System.currentTimeMillis() + 3600000));
        jwt.setIssuer("authentication-service");
        String token = jwt.encodeToBase64();
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password, userDetails.getAuthorities());
        authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(authentication.getPrincipal()));
        return authenticationToken;
    }
    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }
}

我们需要创建一个Jwt 类,用于生成和验证 JWT 令牌:

public class Jwt {
    private String subject;
    private Date expiration;
    private String issuer;
    public String getSubject() {
        return subject;
    }
    public void setSubject(String subject) {
        this.subject = subject;
    }
    public Date getExpiration() {
        return expiration;
    }
    public void setExpiration(Date expiration) {
        this.expiration = expiration;
    }
    public String getIssuer() {
        return issuer;
    }
    public void setIssuer(String issuer) {
        this.issuer = issuer;
    }
    public String encodeToBase64() {
        Map<String, Object> claims = new HashMap<>();
        claims.put("subject", subject);
        claims.put("expiration", expiration.getTime());
        claims.put("issuer", issuer);
        return Jwts.builder()
             .setClaims(claims)
             .signWith(SignatureAlgorithm.HS512, "secret")
             .compact();
    }
    public static Jwt decodeFromBase64(String token) {
        Claims claims = Jwts.parser()
             .setSigningKey("secret")
             .parseClaimsJws(token)
             .getBody();
        Jwt jwt = new Jwt();
        jwt.setSubject(claims.get("subject").toString());
        jwt.setExpiration(new Date((Long) claims.get("expiration")));
        jwt.setIssuer(claims.get("issuer").toString());
        return jwt;
    }
}

我们需要创建一个SecurityConfig 类,用于配置 Spring Security:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private JwtAuthenticationProvider jwtAuthenticationProvider;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
             .csrf().disable()
             .authorizeRequests()
             .antMatchers("/api/**").authenticated()
             .and()
             .httpBasic();
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(jwtAuthenticationProvider);
    }
}

我们需要创建一个TokenFilter 类,用于拦截请求并验证 JWT 令牌:

@Component
public class TokenFilter extends OncePerRequestFilter {
    @Autowired
    private TokenProvider tokenProvider;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String token = tokenProvider.resolveToken(request);
        if (token!= null && tokenProvider.validateToken(token)) {
            filterChain.doFilter(request, response);
        } else {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid token");
        }
    }
}

2、创建应用程序:我们将使用 Spring Boot 框架来创建应用程序,我们需要创建一个 Maven 项目,并添加以下依赖项:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>

我们需要创建一个User 实体类,用于表示用户的信息:

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String username;
    private String password;
    // 省略 getter 和 setter 方法
}

我们需要创建一个UserRepository 接口,用于与数据库进行交互:

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    User findByUsername(String username);
}

我们需要创建一个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 UserDetails() {
            @Override
            public Collection<? extends GrantedAuthority> getAuthorities() {
                return AuthorityUtils.NO_AUTHORITIES;
            }
            @Override
            public String getPassword() {
                return user.getPassword();
            }
            @Override
            public String getUsername() {
                return user.getUsername();
            }
            @Override
            public boolean isAccountNonExpired() {
                return true;
            }
            @Override
            public boolean isAccountNonLocked() {
                return true;
            }
            @Override
            public boolean isCredentialsNonExpired() {
                return true;
            }
            @Override
            public boolean isEnabled() {
                return true;
            }
        };
    }
}

我们需要创建一个AuthenticationProvider 实现类,用于处理用户的认证请求:

@Service
public class JwtAuthenticationProvider implements AuthenticationProvider {
    @Autowired
    private UserDetailsService userDetailsService;
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String username = authentication.getName();
        String password = authentication.getCredentials().toString();
        UserDetails userDetails = userDetailsService.loadUserByUsername(username);
        if (!password.equals(userDetails.getPassword())) {
            throw new BadCredentialsException("Invalid username or password");
        }
        Jwt jwt = new Jwt();
        jwt.setSubject(username);
        jwt.setExpiration(new Date(System.currentTimeMillis() + 3600000));
        jwt.setIssuer("authentication-service");
        String token = jwt.encodeToBase64();
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password, userDetails.getAuthorities());
        authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(authentication.getPrincipal()));
        return authenticationToken;
    }
    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }
}

我们需要创建一个Jwt 类,用于生成和验证 JWT 令牌:

public class Jwt {
    private String subject;
    private Date expiration;
    private String issuer;
    public String getSubject() {
        return subject;
    }
    public void setSubject(String subject) {
        this.subject = subject;
    }
    public Date getExpiration() {
        return expiration;
    }
    public void setExpiration(Date expiration) {
        this.expiration = expiration;
    }
    public String getIssuer() {
        return issuer;
    }
    public void setIssuer(String issuer) {
        this.issuer = issuer;
    }
    public String encodeToBase64() {
        Map<String, Object> claims = new HashMap<>();
        claims.put("subject", subject);
        claims.put("expiration", expiration.getTime());
        claims.put("issuer", issuer);
        return Jwts.builder()
             .setClaims(claims)
             .signWith(SignatureAlgorithm.HS512, "secret")
             .compact();
    }
    public static Jwt decodeFromBase64(String token) {
        Claims claims = Jwts.parser()
             .setSigningKey("secret")
             .parseClaimsJws(token)
             .getBody();
        Jwt jwt = new Jwt();
        jwt.setSubject(claims.get("subject").toString());
        jwt.setExpiration(new Date((Long) claims.get("expiration")));
        jwt.setIssuer(claims.get("issuer").toString());
        return jwt;
    }
}

我们需要创建一个SecurityConfig 类,用于配置 Spring Security:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private JwtAuthenticationProvider jwtAuthenticationProvider;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
             .csrf().disable()
             .authorizeRequests()
             .antMatchers("/api/**").authenticated()
             .and()
             .httpBasic();
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(jwtAuthenticationProvider);
    }
}

我们需要创建一个TokenFilter 类,用于拦截请求并验证 JWT 令牌:

@Component
public class TokenFilter extends OncePerRequestFilter {
    @Autowired
    private TokenProvider tokenProvider;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String token = tokenProvider.resolveToken(request);
        if (token!= null && tokenProvider.validateToken(token)) {
            filterChain.doFilter(request, response);
        } else {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid token");
        }
    }
}

我们需要创建一个UserController 类,用于处理用户的请求:

@RestController
@RequestMapping("/api")
public class UserController {
    @GetMapping("/user")
    public User getUser() {
        // 获取当前用户的信息
        return new User();
    }
}

3、创建前端页面:我们将使用 HTML 和 JavaScript 来创建前端页面,我们需要创建一个index.html 文件,用于显示登录页面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>单点登录示例</title>
</head>
<body>
    <h2>单点登录示例</h2>
    <form action="/login" method="post">
        <label for="username">用户名:</label><input type="text" id="username" name="username"><br>
        <label for="password">密码:</label><input type="password" id="password" name="password"><br>
        <input type="submit" value="登录">
    </form>
</body>
</html>

我们需要创建一个app.js 文件,用于处理登录请求和获取用户信息:

// 引入 jQuery 库
import $ from 'jquery';
// 定义登录函数
function login(username, password) {
    $.ajax({
        url: '/login',
        type: 'post',
        data: {
            username: username,
            password: password
        },
        success: function(response) {
            // 登录成功,跳转到用户页面
            window.location.href = '/user';
        },
        error: function(response) {
            // 登录失败,显示错误信息
            alert('登录失败,请检查用户名和密码是否正确!');
        }
    });
}
// 定义获取用户信息函数
function getUserInfo() {
    $.ajax({
        url: '/user/user',
        type: 'get',

标签: #单点登录 #Java #前端 #代码

黑狐家游戏
  • 评论列表

留言评论