不支持 Spring 安全 Angular Post
Posted
技术标签:
【中文标题】不支持 Spring 安全 Angular Post【英文标题】:Spring security Angular Post not supported 【发布时间】:2016-11-12 06:53:51 【问题描述】:我正在处理待办事项列表,它工作正常,但是当我将 spring security 添加到项目并单击添加时,它给出了
2016-07-10 04:32:34.441 警告 6692 --- [nio-8080-exec-8] os.web.servlet.PageNotFound:请求方法'POST'不是 支持
这个问题的任何解决方案
SpringWebSecurityConfig:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
@Autowired
UserDetailsService userDS;
@Override
protected void configure(HttpSecurity http) throws Exception
http.csrf().disable();
http
.authorizeRequests()
.antMatchers("/register", "/", "/home").permitAll()
.antMatchers("/css/*").permitAll()
.antMatchers("/images/*").anonymous()
.antMatchers("/fonts/*").permitAll()
.antMatchers("/js/**").permitAll()
.antMatchers("/template/**").permitAll()
.antMatchers("/favicon.ico").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.usernameParameter("email")
.passwordParameter("password")
.defaultSuccessUrl("/dashboard")
.permitAll()
.and()
.logout().logoutSuccessUrl("/login?logout")
.permitAll();
@Bean
public BCryptPasswordEncoder passwordEncoder()
return new BCryptPasswordEncoder();
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
auth
.userDetailsService(userDS).passwordEncoder(passwordEncoder());
@Override
protected UserDetailsService userDetailsService()
return userDS;
控制器:
@Controller
public class TaskController
@RequestMapping("/task")
public String task()
return "task";
task.html
<!DOCTYPE html>
<html ng-app="taskManagerApp">
<head>
<meta charset="utf-8"/>
<!--IE Compatibility Meta-->
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<!--first Mobile Meta-->
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Tasks</title>
<!--css fontawesome jb-->
<link href='http://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'/>
<!--My Css File-->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css"/>
<link rel="stylesheet" href="/css/task.css"/>
<link rel="stylesheet" href="/css/animate.css"/>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"/>
<link rel="stylesheet" href="/css/style.css"/>
<!--if IT IE 9-->
<script data-require="angular.js@*" data-semver="1.3.0-beta.14"
src="http://code.angularjs.org/1.3.0-beta.14/angular.js"></script>
<script data-require="angular-animate@*" data-semver="1.3.0-beta.14"
src="http://code.angularjs.org/1.3.0-beta.14/angular-animate.js"></script>
<script type="text/javascript" src="/js/app.js"></script>
<script src="/js/html5shiv.min.js"></script>
<script src="/js/respond.min.js"></script>
<script src="/js/jquery-1.11.1.min.js"></script>
<script src="/js/jquery.nicescroll.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="/js/main-p.js"></script>
<script src="/js/plugin.js"></script>
<!--endif-->
</head>
<body>
<!--==============Start Menu==========-->
<div class="row">
<nav class="navbar navbar-inverse sidebar col-sm-6 col-md-2" role="navigation">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse"
data-target="#bs-sidebar-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Todx</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-sidebar-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><a href="/dashboard"># Dashboard<span style="font-size:16px;"
class="pull-right hidden-xs showopacity glyphicon glyphicon-home"></span></a>
</li>
<li><a href="/chat">Chat<span style="font-size:16px;"
class="pull-right hidden-xs showopacity fa fa-comments"></span></a>
</li>
<li><a href="/task">Tasks<span style="font-size:16px;"
class="pull-right hidden-xs showopacity fa fa-bolt"></span></a>
</li>
<li><a href="/files">Files<span style="font-size:16px;"
class="pull-right hidden-xs showopacity fa fa-paperclip"></span></a>
</li>
<li><a href="/calendar">Calendar<span style="font-size:16px;"
class="pull-right hidden-xs showopacity fa fa-calculator"></span></a>
</li>
<li><a href="/addtocalendar">Add to calendar<span style="font-size:16px;"
class="pull-right hidden-xs showopacity fa fa-calendar-o
"></span></a>
</li>
<li><a href="/hangout">Hangout<span style="font-size:16px;"
class="pull-right hidden-xs showopacity fa fa-video-camera
"></span></a>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Settings <span
class="caret"></span><span style="font-size:16px;"
class="pull-right hidden-xs showopacity glyphicon glyphicon-cog"></span></a>
<ul class="dropdown-menu forAnimate" role="menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li class="divider"></li>
<li><a href="#">Separated link</a></li>
<li class="divider"></li>
<li><a href="#">One more separated link</a></li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
<!--==========End Section Menu=========-->
<!--==========Start Section Project=========-->
<div class="right-side col-xs-11 col-sm-11 col-md-10">
<!--==========Start Navbar=========-->
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="navbar-wrapper">
<div class="container">
<div class="navbar navbar-inverse navbar-static-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse"
data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a id="nav-brand" class="navbar-brand " href="#"><span
class="fa fa-angle-right"></span></a>
</div>
<div class="navbar-collapse collapse horizon-nav">
<ul id="home-page" class="nav navbar-nav ">
<li id="activ"><a href="#"></a></li>
</ul>
<ul id="main-menu" class="nav navbar-nav navbar-right">
<li id="profile"><a id="account" href="#" class="dropdown-toggle ">
<img class="img-circle img-responsive"
src="/images/1.png"
style="margin-left:5; width: 50px;display: inline-flex "/></a>
</li>
<li id="logout"><a href="/logout">logout</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!--==========End Navbar=========-->
<!--==========Start Divs=========-->
<!-- this is main Div that contain navbar divs -->
<div id="content" class="yellow col-xs-12">
<!-- add task here !! -->
<div ng-controller="taskManagerController">
<div id="task-panel" class="fadein fadeout showpanel panel" ng-show="toggle">
<div class="panel-heading ">
<!--<i class="panel-title-icon fa fa-tasks"></i>-->
<div class="panel-heading-controls">
<i class="panel-title-icon fa fa-tasks"></i>
<span class="panel-title">Recent Tasks</span>
<button ng-click="toggle = !toggle" class="btn-md btn-panel ">Add New Task</button>
<button class="btn-md btn-panel " ng-click="archiveTasks()"> Clear completed
<!--ng-confirm-click="Would you like to archive completed tasks?">Clear completed tasks-->
</button>
</div>
</div>
<div class="panel-body">
<div style="text-align: left" class="task" ng-repeat="task in tasks">
<span ng-if="task.taskPriority=='HIGH'" class="priority priority-red">
task.taskPriority
</span>
<span ng-if="task.taskPriority=='MEDIUM'" class="priority priority-yellow">
task.taskPriority
</span>
<span ng-if="task.taskPriority=='LOW'" class="priority priority-green">
task.taskPriority
</span>
<div class="action-checkbox">
<input id="task._links.self.href" type="checkbox" value="task._links.self.href"
ng-checked="selection.indexOf(task._links.self.href) > -1"
ng-click="toggleSelection(task._links.self.href)"/>
<label for="task._links.self.href"></label>
</div>
<div ng-if="task.taskStatus=='COMPLETED'">
<a href="#" class="checkedClass">
task.taskName
<span class="action-status">task.taskStatus</span>
</a>
</div>
<div style="text-align: left" ng-if="task.taskStatus=='ACTIVE'">
<a href="#" class="uncheckedClass">
task.taskName
<span class="action-status">task.taskStatus</span>
</a>
</div>
</div>
</div>
</div>
<div id="add-task-panel" class="fadein fadeout addpanel panel" ng-hide="toggle">
<div class="panel-heading">
<div class="panel-heading-controls">
<i class="panel-title-icon fa fa-plus"></i>
<span class="panel-title panel-title2">Add Task</span>
<button ng-click="toggle = !toggle" class="btn-panel">Show All Tasks</button>
</div>
</div>
<div class="panel-body">
<div class="task">
<table class="add-task">
<tr>
<td>Task Name:</td>
<td><input type="text" ng-model="taskName" class="form-group"/></td>
</tr>
<tr>
<td>Task Description:</td>
<td><input type="text" ng-model="taskDesc" class="form-group"/></td>
</tr>
<tr>
<td>Task Status:</td>
<td>
<select ng-model="taskStatus"
ng-options="status as status for status in statuses">
<option value="">-- Select --</option>
</select>
</td>
</tr>
<tr>
<td>Task Priority:</td>
<td>
<select ng-model="taskPriority"
ng-options="priority as priority for priority in priorities">
<option value="">-- Select --</option>
</select>
</td>
</tr>
<tr>
<td><br/>
<button ng-click="addTask()" class="btn-panel-big"
>Add New Task
</button>
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>
<!--==========End Divs=========-->
</div>
<!--==========End Section Project=========-->
</div>
</body>
</html>
app.js
var taskManagerModule = angular.module('taskManagerApp', ['ngAnimate']);
taskManagerModule.controller('taskManagerController', function ($scope,$http)
var urlBase="";
$scope.toggle=true;
$scope.selection = [];
$scope.statuses=['ACTIVE','COMPLETED'];
$scope.priorities=['HIGH','LOW','MEDIUM'];
$http.defaults.headers.post["Content-Type"] = "application/json";
function findAllTasks()
//get all tasks and display initially
$http.get(urlBase + '/tasks/search/findByTaskArchived?archivedfalse=0').
success(function (data)
if (data._embedded != undefined)
$scope.tasks = data._embedded.tasks;
else
$scope.tasks = [];
for (var i = 0; i < $scope.tasks.length; i++)
if ($scope.tasks[i].taskStatus == 'COMPLETED')
$scope.selection.push($scope.tasks[i].taskId);
$scope.taskName="";
$scope.taskDesc="";
$scope.taskPriority="";
$scope.taskStatus="";
$scope.toggle='!toggle';
);
findAllTasks();
//add a new task
$scope.addTask = function addTask()
if($scope.taskName=="" || $scope.taskDesc=="" || $scope.taskPriority == "" || $scope.taskStatus == "")
alert("Insufficient Data! Please provide values for task name, description, priortiy and status");
else
$http.post(urlBase + '/tasks',
taskName: $scope.taskName,
taskDescription: $scope.taskDesc,
taskPriority: $scope.taskPriority,
taskStatus: $scope.taskStatus
).
success(function(data, status, headers)
alert("Task added");
var newTaskUri = headers()["location"];
console.log("Might be good to GET " + newTaskUri + " and append the task.");
// Refetching EVERYTHING every time can get expensive over time
// Better solution would be to $http.get(headers()["location"]) and add it to the list
findAllTasks();
);
;
// toggle selection for a given task by task id
$scope.toggleSelection = function toggleSelection(taskUri)
var idx = $scope.selection.indexOf(taskUri);
// is currently selected
// HTTP PATCH to ACTIVE state
if (idx > -1)
$http.patch(taskUri, taskStatus: 'ACTIVE' ).
success(function(data)
alert("Task unmarked");
findAllTasks();
);
$scope.selection.splice(idx, 1);
// is newly selected
// HTTP PATCH to COMPLETED state
else
$http.patch(taskUri, taskStatus: 'COMPLETED' ).
success(function(data)
alert("Task marked completed");
findAllTasks();
);
$scope.selection.push(taskUri);
;
// Archive Completed Tasks
$scope.archiveTasks = function archiveTasks()
$scope.selection.forEach(function(taskUri)
if (taskUri != undefined)
$http.patch(taskUri, taskArchived: 1);
);
alert("Successfully Archived");
console.log("It's risky to run this without confirming all the patches are done. when.js is great for that");
findAllTasks();
;
);
//Angularjs Directive for confirm dialog box
taskManagerModule.directive('ngConfirmClick', [
function()
return
link: function (scope, element, attr)
var msg = attr.ngConfirmClick || "Are you sure?";
var clickAction = attr.confirmedClick;
element.bind('click',function (event)
if ( window.confirm(msg) )
scope.$eval(clickAction);
);
;
]);
请注意,让它工作并检索所有任务,但帖子在网络开发人员 chrome 控制台中给出 405,我认为它在 spring security 中它之前在 spring security 上工作,但我不知道我做了什么,现在它不工作
【问题讨论】:
您发送 POST 的 URL 是什么?您可以发布处理该请求的控制器吗? 我将它以角度发布到 /tasks 您是否尝试设置接受标头?您的浏览器可能正在设置接受标头,而您的标头可能没有说它可以接受。 我听不懂 【参考方案1】:默认情况下,假定所有对 URL 的传入请求都是 HTTP GET 类型。为了区分HTTP请求类型的映射,我们需要在@RequestMapping声明中明确指定HTTP请求方法
如果你尝试 POST 到这个 URL,Spring 会拒绝它。
尝试将注释更改为
@RequestMapping(value = "/task", method = RequestMethod.POST)
public String task()
return "task";
如果您已经有当前 GET 方法的外部引用,您仍然可以为 POST 方法创建附加定义,以便两者可以共存。您只需像这样为它们分配不同的 Java 方法名称
@RequestMapping(value = "/task", method = RequestMethod.GET)
public String task()
return "task";
@RequestMapping(value = "/task", method = RequestMethod.POST)
public String postTask()
return "task";
更新 1
如果你的控制器打算接收 Ajax 调用,你需要添加额外的注解(比如@ResponseBody)让 Spring MVC 知道这是一个支持 ajax 的控制器/方法
@ResponseBody
@RequestMapping(value = "/task", method = RequestMethod.POST)
public String task()
return "task";
更新 2
试试下面的。真的,我不知道 Spring Security 是否强制执行参数与方法签名,但可能是您的情况。
public String task(@RequestParam(value = "taskName") String taskName,
@RequestParam(value = "taskDescription") String taskDescription,
@RequestParam(value = "taskPriority") String taskPriority,
@RequestParam(value = "taskStatus") String taskStatus)
return "task";
【讨论】:
不,它不工作,加上它在添加弹簧安全之前工作 这不是 Spring 安全问题,因为它们返回 401 错误(禁止)。请看更新 它返回 405 错误:“方法不允许”异常:“org.springframework.web.HttpRequestMethodNotSupportedException”消息:“请求方法 'POST' 不支持”路径:“/tasks”状态:405时间戳:“2016-07-10T03:17:00.497+0000” 您是否将参数作为 JSON 发送到您的“/task”控制器? 我没有将它发送到 /task 控制器我使用 mongo data rest with angular 我在控制器中使用 /task 来检索页面【参考方案2】:我发现我让另一个控制器访问 /files 的问题 与角度的post方法冲突
【讨论】:
以上是关于不支持 Spring 安全 Angular Post的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Rest 和 Spring 安全性通过 ldap 登录 Angular?
发布请求不适用于 Spring 安全性和 Angular 5
带有 Spring 安全 webflux 的 Angular 6 被 CORS 阻止