- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我已经构建了一个使用 jwt
身份验证的 Spring-Boot
应用程序。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.diplie</groupId>
<artifactId>rest-api</artifactId>
<version>1.0.0</version>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.0.RC1</version>
</parent>
<properties>
<springfox-version>2.2.2</springfox-version>
<java.version>1.8</java.version>
<maven.test.skip>true</maven.test.skip>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>LATEST</version>
</dependency>
<!-- Swagger 2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox-version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox-version}</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>${project.parent.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>repository.springsource.milestone</id>
<name>SpringSource Milestone Repository</name>
<url>http://repo.springsource.org/milestone</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>repository.springsource.milestone</id>
<name>SpringSource Milestone Repository</name>
<url>http://repo.springsource.org/milestone</url>
</pluginRepository>
</pluginRepositories>
</project>
我想要一个基本的身份验证,当我使用 Swagger
我想要一个弹出窗口,当我点击 Try Out
按钮时
例如:
如何在同一个端点上使用 spring 安全的两个安全(表单基础,JWT token )过滤器?
WebSecurityConfig
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.exceptionHandling().and().anonymous().and().servletApi().and().authorizeRequests()
// Allow anonymous resource requests
.antMatchers("/swagger-ui.html").permitAll().antMatchers("/").permitAll()
.antMatchers("/webjars/springfox-swagger-ui/**").permitAll().antMatchers("/swagger-resources/**")
.permitAll().antMatchers("/v2/api-docs").permitAll().antMatchers("/favicon.ico").permitAll()
.antMatchers("**/*.html").permitAll().antMatchers("**/*.css").permitAll().antMatchers("**/*.js")
.permitAll()
// Allow anonymous logins
.antMatchers("/user/User").permitAll().antMatchers("/locality/**").hasAuthority("Admin")
.antMatchers("/category/**").hasAuthority("Admin").antMatchers("/item").hasAuthority("Item")
.antMatchers("/item/userItems").hasAuthority("Item").antMatchers("item/lookFor").permitAll()
.antMatchers("item/items").hasAuthority("User")
// All other request need to be authenticated
.anyRequest().authenticated().and()
// And filter other requests to check the presence of JWT in
// header
.addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// Créer un compte par défaut
auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN");
}
}
TokenAuthenticationService
public class TokenAuthenticationService {
static ResourceBundle bundle = ResourceBundle.getBundle("application");
static void addAuthentication(HttpServletResponse res, String username) {
String JWT = Jwts.builder().setSubject(username)
.setExpiration(new Date(System.currentTimeMillis() + getExpirationTime()))
.signWith(SignatureAlgorithm.HS512, getSecret()).compact();
res.addHeader(getHeaderString(), getTokenPrefix() + " " + JWT);
}
static Authentication getAuthentication(HttpServletRequest request) {
String token = request.getHeader(getHeaderString());
if (token != null) {
// Analyse du jeton.
String user = Jwts.parser().setSigningKey(getSecret()).parseClaimsJws(token.replace(getTokenPrefix(), ""))
.getBody().getSubject();
return user != null ? new UsernamePasswordAuthenticationToken(user, null, emptyList()) : null;
}
return null;
}
/**
* @return the secret
*/
public static String getSecret() {
return bundle.getString("secret");
}
/**
* @return the expirationTime
*/
public static long getExpirationTime() {
return Long.valueOf(bundle.getString("expiration.time"));
}
/**
* @return the tokenPrefix
*/
public static String getTokenPrefix() {
return bundle.getString("token.prefix");
}
/**
* @return the headerString
*/
public static String getHeaderString() {
return bundle.getString("header.string");
}
}
JWTLoginFilter
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter {
public JWTLoginFilter(String url, AuthenticationManager authManager) {
super(new AntPathRequestMatcher(url));
setAuthenticationManager(authManager);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
throws AuthenticationException, IOException, ServletException {
AccountCredentials creds = new ObjectMapper().readValue(req.getInputStream(), AccountCredentials.class);
return getAuthenticationManager().authenticate(new UsernamePasswordAuthenticationToken(creds.getUsername(),
creds.getPassword(), Collections.emptyList()));
}
@Override
protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain,
Authentication auth) throws IOException, ServletException {
TokenAuthenticationService.addAuthentication(res, auth.getName());
}
}
JWTAuthenticationFilter
public class JWTAuthenticationFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
Authentication authentication = TokenAuthenticationService.getAuthentication((HttpServletRequest) request);
SecurityContextHolder.getContext().setAuthentication(authentication);
filterChain.doFilter(request, response);
}
}
AccountCredentials
public class AccountCredentials {
private String username;
private String password;
/**
*
*/
public AccountCredentials() {
super();
}
/**
* @return the username
*/
public String getUsername() {
return username;
}
/**
* @param username
* the username to set
*/
public void setUsername(String username) {
this.username = username;
}
/**
* @return the password
*/
public String getPassword() {
return password;
}
/**
* @param password
* the password to set
*/
public void setPassword(String password) {
this.password = password;
}
}
最佳答案
您必须使用不同的根 URL 创建两个不同的 WebSecurityConfigurerAdapter
配置。如果 URL 重叠(即 /admin 和/**
),那么您将需要在配置中使用 @Order
注释来定义优先级。
这是基于 HTTP 基本和表单的身份验证的工作示例。
https://github.com/ConsciousObserver/TestMultipleLoginPagesFormAndBasic.git
package com.test;
import javax.servlet.http.HttpSession;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
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.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@SpringBootApplication
public class TestMultipleLoginPagesApplication {
public static void main(String[] args) {
SpringApplication.run(TestMultipleLoginPagesApplication.class, args);
}
}
@Controller
class MvcController {
@RequestMapping(path="form/formLogin", method=RequestMethod.GET)
public String formLoginPage() {
return "formLogin";
}
@RequestMapping(path="form/formHome", method=RequestMethod.GET)
public String formHomePage() {
return "formHome";
}
@RequestMapping(path="basic/basicHome", method=RequestMethod.GET)
public String userHomePage() {
return "basicHome";
}
@RequestMapping(path="basic/logout", method=RequestMethod.GET)
public String userLogout(HttpSession session) {
session.invalidate();
return "basicLogout";
}
}
@Configuration
@Order(1)
class FormSecurity extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/form/**")
.authorizeRequests()
.anyRequest().hasRole("FORM_USER")
.and()
.formLogin()
.loginPage("/form/formLogin").permitAll()
.loginProcessingUrl("/form/formLoginPost").permitAll()
.defaultSuccessUrl("/form/formHome")
.and()
.logout().logoutUrl("/form/logout").logoutSuccessUrl("/form/formLogin")
.and()
.httpBasic().disable()
.csrf().disable();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user")
.password("test")
.roles("FORM_USER");
}
}
@Configuration
@Order(2)
class BasicAuthSecurity extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/basic/**")
.authorizeRequests()
.anyRequest().hasRole("BASIC_USER")
.antMatchers("/basic/logout").permitAll()
.and()
.httpBasic()
.and()
.csrf().disable();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("basic_user")
.password("test")
.roles("BASIC_USER");
}
}
@Configuration
@Order(3)
class RootUrlSecurity extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
/*
* Put any security expectations from the root URL here, currently everything is permitted.
* Since it's the last in the order /form/** and /basic/** have a priority over it.
*/
http.antMatcher("/**")
.authorizeRequests()
.anyRequest().permitAll();
}
}
注意:由于这些登录页面并非来自不同的应用程序,因此它们共享 SecurityContextHolder 或安全上下文。因此,如果您从一个登录页面登录,然后尝试转到另一个 protected 资源,您将不会被重定向到下一个登录页面。相反,您将获得 403(取决于不同登录页面分配的角色)。一次只能维持一个登录 session 。
关于java - 如何在 Spring Boot 中使用 JWT 身份验证实现基本身份验证?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44302457/
我正在使用SQL Server 2008 R2,并且想创建一个触发器。 对于每个添加(仅添加),将像这样更新一列: ABC-CurrentYear-AutoIncrementCode 例子: ABC-
是否可以在显示最终一致性的数据存储中创建/存储用户帐户? 似乎不可能在没有一堆架构复杂性的情况下管理帐户创建,以避免可能发生具有相同 UID(例如电子邮件地址)的两个帐户的情况? 最终一致性存储的用户
您好, 我有一个带有 Identity 的 .NetCore MVC APP并使用 this指导我能够创建自定义用户验证器。 public class UserDomainValidator : IU
这与以下问题相同:HiLo or identity? 我们以本站的数据库为例。 假设该站点具有以下表格: 帖子。 投票。 注释。 使用它的最佳策略是什么: 身份 - 这是更常见的。 或者 HiLo -
我想将 Blazor Server 与 ASP.NET Identity 一起使用。但我需要使用 PostgreSQL 作为用户/角色存储,因为它在 AWS 中。 它不使用 EF,这是我需要的。 我创
我正在开发一个 .NET 应用程序,它可以使用 Graph API 代表用户发送电子邮件。 提示用户对应用程序进行授权;然后使用获取的访问 token 来调用 Graph API。刷新 token 用
我使用 ASP.NET 身份和 ClaimsIdentity 来验证我的用户。当用户通过身份验证时,属性 User.Identity 包含一个 ClaimsIdentity 实例。 但是,在登录请求期
所以我在两台机器上都安装了 CYGWIN。 如果我这样做,它会起作用: ssh -i desktop_rsa root@remoteserver 这需要我输入密码 ssh root@remoteser
我尝试在 mac osx 上的终端中通过 telnet 连接到 TOR 并请求新身份,但它不起作用,我总是收到此错误消息: Trying 127.0.0.1... telnet: connect to
我正在开发一个 .NET 应用程序,它可以使用 Graph API 代表用户发送电子邮件。 提示用户对应用程序进行授权;然后使用获取的访问 token 来调用 Graph API。刷新 token 用
我正在开发一项服务,客户可以在其中注册他们的 webhook URL,我将发送有关已注册 URL 的更新。为了安全起见,我想让客户端(接收方)识别是我(服务器)向他们发送请求。 Facebook和 G
在 Haskell 中,有没有办法测试两个 IORef 是否相同?我正在寻找这样的东西: IORef a -> IORef a -> IO Bool 例如,如果您想可视化由 IORef 组成的图形,这
我是 .NET、MVC 和身份框架的新手。我注意到身份框架允许通过注释保护单个 Controller 操作。 [Authorize] public ActionResult Edit(int? Id)
我有一列具有身份的列,其计数为19546542,我想在删除所有数据后将其重置。我需要类似ms sql中的'dbcc checkident'这样的内容,但在Oracle中 最佳答案 在Oracle 12
这是我用来创建 session 以发送电子邮件的代码: props.put("mail.smtp.auth", "true"); props.put("mail.smtp.starttls.enabl
我想了解 [AllowAnonymous] 标签的工作原理。 我有以下方法 [HttpGet] public ActionResult Add() { return View(); } 当我没
在使用沙盒测试环境时,PayPal 身份 token 对某些人显示而不对其他人显示的原因是否有任何原因。 我在英国使用 API,终生无法生成或找到 token 。 我已经遵循协议(protocol)并
我对非常简单的事情有一些疑问:IDENTITY。我尝试在 phpMyAdmin 中创建表: CREATE TABLE IF NOT EXISTS typEventu ( typEventu
习语 #1 和 #5 是 FinnAPL Idiom Library两者具有相同的名称:“Progressive index of (without replacement)”: ((⍴X)⍴⍋⍋X⍳
当我第一次在 TFS 中设置时,我的公司拼错了我的用户名。此后他们将其更改为正确的拼写,但该更改显然未反射(reflect)在 TFS 中。当我尝试 checkin 更改时,出现此错误: 有没有一种方
我是一名优秀的程序员,十分优秀!