Bei Verwendung von Spring Security haben wir dies in Form von Reverse Pull zusammengefasst. Die Antwort hier ist nicht die richtige Antwort, es ist nur eine Methode, daher würde ich es begrüßen, wenn Sie darauf verweisen könnten, wenn Sie sich über die Implementierung nicht sicher sind.
Die Referenz wird von Zeit zu Zeit aktualisiert.
Artikel | Ausführung |
---|---|
Java | 8 |
Spring Boot | 2.2.4 |
Unten finden Sie den minimal erforderlichen Code.
Begrenzen Sie alle Anfragen
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.authenticated();
}
}
Da wir diesmal keine Verbindung zur Datenbank herstellen, verwenden wir die folgenden Authentifizierungsinformationen.
application.yml
spring:
security:
user:
name: user
password: pass
roles: USER
SecurityConfig.java
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/","/login") // 「/」「/Auf "Login" kann ohne Authentifizierung zugegriffen werden
.permitAll()
.anyRequest()
.authenticated();
}
}
CSRF ist standardmäßig aktiviert.
SecurityConfig.java
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.authenticated();
http.csrf().disable();
}
}
SecurityConfig.java
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.authenticated();
http.cors().configurationSource(getCorsConfigurationSource());
}
private CorsConfigurationSource getCorsConfigurationSource() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
//Erlaube alle Methoden
corsConfiguration.addAllowedMethod(CorsConfiguration.ALL);
//Alle Header zulassen
corsConfiguration.addAllowedHeader(CorsConfiguration.ALL);
//Erlaube alle Ursprünge
corsConfiguration.addAllowedOrigin(CorsConfiguration.ALL);
UrlBasedCorsConfigurationSource corsSource = new UrlBasedCorsConfigurationSource();
//Kann für jeden Pfad eingestellt werden. Hier für alle Pfade eingestellt
corsSource.registerCorsConfiguration("/**", corsConfiguration);
return corsSource;
}
}
authenticationprovider
Erstellen Sie eine Implementierungsklasse für.
CustomeAuthenticationProvider.java
@Configuration
public class CustomeAuthenticationProvider implements AuthenticationProvider {
//Authentifizierungsprozess
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = (String) authentication.getPrincipal();
String password = (String) authentication.getCredentials();
if (!"user".equals(username) || !"password".equals(password)) {
throw new BadCredentialsException("Falsche Anmeldeinformationen");
}
return new UsernamePasswordAuthenticationToken(username, password, new ArrayList<>());
}
@Override
public boolean supports(Class<?> authentication) {
return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
}
}
securityconfig
Geben Sie den oben erstellten Anbieter in an.
SecurityConfig.java
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomeAuthenticationProvider authenticationProvider;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.authenticated();
http.formLogin();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//Geben Sie den oben erstellten Anbieter an
auth.authenticationProvider(authenticationProvider);
}
}
SecurityConfig.java
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.authenticated();
http.formLogin();
}
}
/login
Wenn Sie darauf zugreifen, wird der von Spring Security vorbereitete Anmeldebildschirm angezeigt.
Bereiten Sie den HTML-Code für den Anmeldebildschirm vor.
login.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Einloggen</title>
</head>
<body>
<form th:action="@{/login}" method="post">
<input type="text" name="username">
<input type="password" name="password">
<button type="submit">Einloggen</button>
</form>
</body>
</html>
SecurityConfig.java
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("(A)") //hinzufügen
.permitAll() //hinzufügen
.anyRequest()
.authenticated()
http.formLogin()
.loginPage("(A)"); //hinzufügen
}
}
Standardmäßig erhalten Sie es mit den Parameternamen `Benutzername``` und
Passwort```.
SecurityConfig.java
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/(A)") //① bestanden
.permitAll()
.anyRequest()
.authenticated()
http.formLogin()
.loginPage("/(A)")
.usernameParameter("(B)") //hinzufügen
.passwordParameter("(C)"); //hinzufügen
}
}
login.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Einloggen</title>
</head>
<body>
<form th:action="@{/login}" method="post">
<input type="text" name="(B)">
<input type="password" name="(C)">
<button type="submit">Einloggen</button>
</form>
</body>
</html>
Standardmäßig wechselt es zu "/".
SecurityConfig.java
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.authenticated()
http.formLogin()
.defaultSuccessUrl("/home"); // 「/Übergang zu "Zuhause"
}
}
Normalerweise werden Sie mit zwei Parametern authentifiziert, `Benutzername``` und`
Passwort```.
Es gibt verschiedene Methoden, aber hier ist die Methode zur Formularauthentifizierung.
Bereiten Sie einen Anmeldebildschirm vor, um die drei Parameter einzugeben.
login.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Einloggen</title>
</head>
<body>
<form th:action="@{/login}" method="post">
<input type="text" name="(A)">
<input type="text" name="username">
<input type="password" name="password">
<button type="submit">Einloggen</button>
</form>
</body>
</html>
Erstellen Sie eine Klasse, die das `` `UsernamePasswordAuthenticationToken``` erbt, das die Anmeldeinformationen enthält.
MultiParamAuthenticationToken
public class MultiParamAuthenticationToken extends UsernamePasswordAuthenticationToken {
private static final long serialVersionUID = 1L;
private Object tenant; //Zusätzliche Parameter
public MultiParamAuthenticationToken(Object principal, Object credentials, Object tenant) {
super(principal, credentials, Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")));
this.tenant = tenant;
}
public Object getTenant() {
return this.tenant;
}
}
Erstellen Sie eine Authentifizierungsanbieterklasse.
MultiParamAuthenticationProvider
@Configuration
public class MultiParamAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = (String) authentication.getPrincipal();
String password = (String) authentication.getCredentials();
String tenant = null;
if (authentication instanceof MultiParamAuthenticationToken) {
tenant = (String) ((MultiParamAuthenticationToken) authentication).getTenant();
}
if (!"user".equals(username) || !"pass".equals(password) || !"multi".equals(tenant)) {
throw new BadCredentialsException("aaa");
}
return new MultiParamAuthenticationToken(username, password, tenant);
}
@Override
public boolean supports(Class<?> authentication) {
return MultiParamAuthenticationToken.class.isAssignableFrom(authentication);
}
}
Bereiten Sie eine Filterklasse vor, um den dritten Parameter zu erhalten.
MultiParamAuthenticationFilter
public class MultiParamAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) {
String username = obtainUsername(request);
String password = obtainPassword(request);
String tenant = obtainTenant(request);
MultiParamAuthenticationToken authRequest = new MultiParamAuthenticationToken(
username, password, tenant);
return getAuthenticationManager().authenticate(authRequest);
}
private String obtainTenant(HttpServletRequest request) {
return (String) request.getParameter("tenant");
}
}
SecurityConfig.java
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private MultiParamAuthenticationProvider authenticationProvider;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login")
.permitAll()
.anyRequest()
.authenticated();
//Stellen Sie Ihren eigenen Filter ein, ohne formLogin zu verwenden
http.addFilter(getMultiParamAuthenticationFilter());
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider);
}
private MultiParamAuthenticationFilter getMultiParamAuthenticationFilter() throws Exception {
MultiParamAuthenticationFilter filter = new MultiParamAuthenticationFilter();
filter.setAuthenticationManager(authenticationManager());
return filter;
}
}
Um die OAuth-Authentifizierung durchzuführen, muss der Authentifizierungsanbieter eine Client-ID und ein Geheimnis ausgeben. Hier wird die OAuth-Authentifizierung von Google durchgeführt.
Fügen Sie pom.xml die folgende Abhängigkeit hinzu.
pom.xml
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
Legen Sie die OAuth-Informationen in application.yml fest.
application.yml
spring:
security:
oauth2:
client:
registration:
google:
clientId: <Kunden ID>
clientSecret: <Kundengeheimnis>
SpringSecurity.java
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.authenticated();
http.oauth2Login(); //hinzufügen
}
LoginController.java
@Controller
public class LoginController {
@Autowired
private OAuth2AuthorizedClientService authorizedClientService;
@GetMapping
public String index(OAuth2AuthenticationToken authentication, Model model) {
OAuth2AuthorizedClient authorizedClient = this.authorizedClientService.loadAuthorizedClient(
authentication.getAuthorizedClientRegistrationId(),
authentication.getName());
model.addAttribute("name", authorizedClient.getPrincipalName());
model.addAttribute("accessToken", authorizedClient.getAccessToken().getTokenValue());
return "index";
}
oauth2authenticationtoken
Sie können die Authentifizierungsinformationen mit abrufen.
Erstellen Sie als Nächstes einen Bildschirm für die Anzeige.
index.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Zuhause</title>
</head>
<body>
<p th:text="${accessToken}"></p>
<p th:text="${name}"></p>
</body>
</html>
Erstellen Sie einen Anmeldebildschirm.
login.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Einloggen</title>
</head>
<body>
<a href="/oauth2/authorization/google">Google-Authentifizierung</a>
</body>
</html>
SecurityConfig.java
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("(A)")
.permitAll()
.anyRequest()
.authenticated();
http.oauth2Login().loginPage("(A)"); //hinzufügen
}
usernamepasswordauthenticationfilter
Erstellen Sie eine Klasse, die von erbt.
JsonAuthenticationFilter.java
public class JsonAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) {
try {
//Parameter abrufen
//Informationen zu Authentifizierungsparametern sind erforderlich.getInputStream()Da es in gespeichert ist, wird es mit Jackson herausgenommen
Map<String, String> params = new ObjectMapper().readValue(request.getInputStream(),
new TypeReference<Map<String, String>>() {});
//Generierung von Authentifizierungsanforderungsinformationen
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
params.get("(A)"), params.get("(B)"));
//Authentifizierung
return getAuthenticationManager().authenticate(authRequest);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
//Prozess, wenn die Authentifizierung erfolgreich ist
@Override
protected void successfulAuthentication(HttpServletRequest req,
HttpServletResponse res,
FilterChain chain,
Authentication auth) throws IOException, ServletException {
//Authentifizierten Benutzer speichern
//Wenn Sie es nicht speichern, wird es als nicht protokolliert behandelt
SecurityContextHolder.getContext().setAuthentication(auth);
}
}
Der Anmeldebildschirm sendet die Anmeldeinformationen über die Ajax-Kommunikation.
login.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Einloggen</title>
</head>
<body>
<form>
<input type="text" id="(A)" name="(A)">
<input type="password" id="(B)" name="(B)">
<button type="button" id="btnLogin" onclick="login()">Einloggen</button>
</form>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
function login() {
//Authentifizierungsparameter abrufen
const data = {
email: document.getElementById('(A)').value,
password: document.getElementById('(B)').value
}
//Authentifizierung
axios.post('(C)', data)
.then(res => location.href = "/home") //Wenn die Authentifizierung erfolgreich ist, "/Übergang zu "Zuhause"
}
</script>
</body>
</html>
Stellen Sie den oben mit SecuritConfig erstellten Filter ein.
SecurityConfig.java
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("(C)")
.permitAll()
.anyRequest()
.authenticated();
//Die Ajax-Kommunikation wird ausgeführt. Deaktivieren Sie sie daher
http.csrf().disable();
//Stellen Sie den Authentifizierungsfilter von Json ein
http.addFilter(getJsonAuthenticationFilter());
}
private JsonAuthenticationFilter getJsonAuthenticationFilter() throws Exception {
JsonAuthenticationFilter filter = new JsonAuthenticationFilter();
//Verwenden Sie die Standardauthentifizierungsmethode
filter.setAuthenticationManager(authenticationManager());
//Geben Sie den Pfad an, in dem der Filter ausgeführt werden soll, und die HTTP-Methode
filter.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("(C)", "POST"));
return filter;
}
}
Fügen Sie die JWT-Bibliothek zu pom.xml hinzu.
pom.xml (nur zusätzlich)
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
Senden Sie die Anmeldeinformationen in JSON und geben Sie die JWT nach Erfolg zurück.
usernamepasswordauthenticationfilter
Erstellen Sie eine Klasse, die von erbt.
JwtAuthenticationFilter.java
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) {
try {
//Parameter abrufen
//Informationen zu Authentifizierungsparametern sind erforderlich.getInputStream()Da es in gespeichert ist, wird es mit Jackson herausgenommen
Map<String, String> params = new ObjectMapper().readValue(request.getInputStream(),
new TypeReference<Map<String, String>>() {});
//Generierung von Authentifizierungsanforderungsinformationen
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
params.get("(A)"), params.get("(B)"));
//Authentifizierung
return getAuthenticationManager().authenticate(authRequest);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
//Erstellen Sie JWT, wenn die Authentifizierung erfolgreich ist, und legen Sie es im Antwortheader fest.
@Override
protected void successfulAuthentication(HttpServletRequest req,
HttpServletResponse res,
FilterChain chain,
Authentication auth) throws IOException, ServletException {
Date issuedAt = new Date();
Date notBefore = new Date(issuedAt.getTime());
Date expiresAt = new Date(issuedAt.getTime() + TimeUnit.MINUTES.toMillis(100L));
//JWT-Generation
String token = JWT.create()
.withIssuedAt(issuedAt)
.withNotBefore(notBefore)
.withExpiresAt(expiresAt)
.withClaim("(C)", (String)auth.getPrincipal())
.sign(Algorithm.HMAC512("secret"));
//Stellen Sie JWT im Autorisierungsheader ein
res.addHeader("Authorization", "Bearer " + token);
}
}
onceperrequestfilter
Erstellen Sie eine Klasse, die jwt überprüft, von dem geerbt wird.
JwtAuthenticationFilter.java
public class JwtAuthorizationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
throws ServletException, IOException {
String header = req.getHeader("Authorization");
if (header == null || !header.startsWith("Bearer ")) {
//Setzt die Verarbeitung fort, legt jedoch keine Anmeldeinformationen in SecurityContext fest, was zur Rückgabe von 403 führt
chain.doFilter(req, res);
return;
}
//Wenn es sich um ein Trägerpräfix im Autorisierungsheader handelt
UsernamePasswordAuthenticationToken authentication = getAuthentication(req);
if (Objects.isNull(authentication)) {
chain.doFilter(req, res);
return;
}
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(req, res);
}
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
String token = request.getHeader("Authorization");
if (token == null || !token.startsWith("Bearer ")) {
return null;
}
token = token.substring("Bearer ".length());
if (Objects.isNull(token) || token.length() == 0) {
return null;
}
JWTVerifier verifier = JWT.require(Algorithm.HMAC512("secret")).build();
try {
DecodedJWT jwt = verifier.verify(token);
return new UsernamePasswordAuthenticationToken(
jwt.getClaim("(C)").asString(), null,
null);
} catch (JWTDecodeException e) {
return null;
}
}
}
SecurityConfig.java
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login")
.permitAll()
.anyRequest()
.authenticated();
http.csrf().disable();
http.addFilter(getJsonAuthenticationFilter());
}
private JsonAuthenticationFilter getJsonAuthenticationFilter() throws Exception {
JsonAuthenticationFilter filter = new JsonAuthenticationFilter();
//Verwenden Sie die Standardauthentifizierungsmethode
filter.setAuthenticationManager(authenticationManager());
//Geben Sie den Pfad an, in dem der Filter ausgeführt werden soll, und die HTTP-Methode
filter.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/login", "POST"));
return filter;
}
}
Recommended Posts