- 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/
如何将十进制数字转换为mixed radix表示法? 我猜想给定每个基数数组的输入和十进制数,它应该输出每列值的数组。 最佳答案 伪代码: bases = [24, 60, 60] input = 8
我有 Table-A,其中有“x”行。 (对于这个例子有 8 行) 我通过使用游标创建了列数为“x”的Table-C。 (使其动态化;如果将更多行添加到 Table-A,则会在 Table-C 中创建
我有一个关于对象的(很可能是简单而愚蠢的)问题。我创建了实例“Person”的对象“jon”。当我打电话时 console.log(jon.name) 控制台会给我输出“jon”。到目前为止,一切都很
这个问题已经有答案了: 已关闭11 年前。 Possible Duplicate: javascript function vs. ( function() { … } ()); 抱歉,如果这太基础了
我正在尝试用 Java 重新创建射弹轨迹,但是,我遇到了一些问题。我看过很多解释公式之类的视频,但他们的方程中有一个目标,而我没有。我的意思是,他们有一个范围来计算子弹的下落,但我试图弄清楚子弹最终会
(希望如此)来自一个完整的 Rust 初学者的一个简单问题。我的循环有什么问题? num 计算结果为“69”的速度相当快,但是一旦 num 设置为“69”,循环就永远不会退出。我肯定遗漏了一些明显的东
我在 id="name"的元素上应用“.length”,但它计数为 29 而不是 14。我想知道我的错误在哪里?如果有人可以让我知道,那就太好了。谢谢! var name=document.getEl
我知道这很简单,但由于某种原因我无法让它工作。我正在尝试在 Java 中创建自定义颜色,但它似乎不起作用。 import java.awt.Color; Color deepGreen = new C
我有一个大文件,其中每一行都包含一个子字符串,例如 ABC123。如果我执行 grep ABC file.txt 或 grep ABC1 file.txt 我按预期返回这些行,但如果我执行 grep
我想将以下实体映射转换为 Priority 对象。在 getter 上,当我将“Short”更改为“Priority”并遵循 this.priority 时,它会提示 'basic' 属性类型不应该是
我正在开发一个相当基本的函数,我发现很难弄清楚为什么我会得到我的输出。 def mystery(n): print(n) if n < 4: my
我正在尝试对 WordPress 安装的新闻部分实现同位素过滤。我是 JavaScript/jQuery 的新手,正在尝试随时随地学习。我首先使用 Filters section of the Iso
已关闭。这个问题是 not reproducible or was caused by typos 。目前不接受答案。 这个问题是由拼写错误或无法再重现的问题引起的。虽然类似的问题可能是 on-top
我在另一个实体类中引用一个实体并收到此错误。下面是示例代码。我在 persistence.xml 中也有这些类。 是什么导致了这个问题?我正在使用 Spring 数据 JPA 和 Hibernate。
我正在解析 HTML 并重新格式化图像以使其更好地适应。由于某种原因,当我有多个图像需要解析时,我会超出范围,而且我一生都无法弄清楚为什么。 当 imgArray.count >1 时,我将使用带有递
我是 SQL 新手,正在尝试创建一个基本的子查询。我需要找出经理的平均年龄和实习生的平均年龄之间的差异。 标题为一栏 - 经理或实习生年龄是一列,全部在同一个表中。 我会使用两个子查询来做类似的事情:
我习惯了 csh,所以不得不使用 bash 有点烦人。这段代码有什么问题? if[$time > 0300] && [$time 和 300 && time < 900 )) then mod
我建立了这个页面:http://excelwrestling.com/poola.php即将到来的双重锦标赛。我的大部分数据都是从我的 mySQL 数据库中提取的,现在只有一些示例数据。 我希望链接选
是否有任何原因导致以下内容不起作用: for (i=0;i < someArray.length;i++) { if (someArray[i].indexOf("something") !=
我现在正在学习 Javascript,有一个问题一直困扰着我! 因此,我在这里所需要做的就是在此输入框中键入颜色,单击按钮并将标题更改为键入的颜色(仅当键入的颜色位于变量中指定的数组中时)。 我的代码
我是一名优秀的程序员,十分优秀!