我正在尝试保护一些静态HTML页面,因为我正在使用Angularjs,而某些HTML部分页面只能由具有特定角色的用户访问。
所以我尝试在我的WEB-INF文件夹中创建一个名为private的文件夹,然后将我的HTML文件放在那里,然后在我的Spring安全配置文件中输入这些带有注释hasAnyAuthority的文件的路径
.antMatchers("/privatePartials/protectedPartial.html").hasAnyAuthority("roleA")
我也试过像这样的hasROle注释
.antMatchers("/privatePartials/protectedPartial.html").access("hasRole('roleA')")
但是我收到了403错误,就好像我的用户没有“roleA”但它拥有它,因为我在我的控制台中打印了用户登录时所具有的所有角色。
我还尝试在我的资源文件夹中创建一个文件夹,但它也不起作用,因为任何用户都可以查看受保护的页面,这与用户的角色无关。我认为这是因为我在我的安全配置类中使用了这种方法,允许所有用户访问所有资源。
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**", "/index.jsp", "/login.jsp",
"/template/**", "/", "/error/**");
}
那么如何使用Spring Security保护这个HTML部分页面,
我正在使用Spring MVC 4.2.5.RELEASE
和Spring Secuirty 4.1.0.RELEASE
这是我的文件夹结构
SpringMVCProject
--Web-Pages
--WEB-INF
--resources
--angular
--controllers
userController.js
--services
userService.js
--partials
--userPartials
deleteuser.html
app.js
permissionConstants.js
routes.js
--css
--private
--privatePartials
protegida.html
--views
index.html
--Source Packages
--controllers
--userControllers
UserController.java
--secuirty
SecuirtyConfig.java
这是我的整个安全配置类
public class SegurityConfig extends WebSecurityConfigurerAdapter {
public SegurityConfig() {
super();
}
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private RestUnauthorizedEntryPoint restAuthenticationEntryPoint;
@Autowired
private AccessDeniedHandler restAccessDeniedHandler;
@Autowired
private AuthenticationSuccessHandler restAuthenticationSuccessHandler;
@Autowired
private AuthenticationFailureHandler restAuthenticationFailureHandler;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/angular/**",
"/resources/bower_components/**",
"/resources/css/**",
"/resources/dist/**",
"/resources/less/**",
"/index.jsp",
"/login.jsp",
"/template/**",
"/",
"/error/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers().disable()
.csrf().disable()
.authorizeRequests()
.antMatchers("/failure").permitAll()
.antMatchers("/v2/api-docs").hasAnyAuthority("admin")
.antMatchers("/users/**").hasAnyAuthority("admin")
.antMatchers("/resources/private/privatePartials/protegida.html").hasAuthority("administrador")
.antMatchers("/views/partials/usuarioTemplates/crearUsuario.html").hasAuthority("administrador")
.anyRequest().authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(restAuthenticationEntryPoint)
.accessDeniedHandler(restAccessDeniedHandler)
.and()
.formLogin()
.loginProcessingUrl("/login")
.successHandler(restAuthenticationSuccessHandler)
.failureHandler(restAuthenticationFailureHandler)
.usernameParameter("username")
.passwordParameter("password")
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler())
.deleteCookies("JSESSIONID")
.permitAll()
.and();
}
这里是我的SpringConfig类
@Configuration
@EnableWebMvc
@ComponentScan({"config", "controllers", "security"})
public class ConfigMVC extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/WEB-INF/resources/");
}
@Bean
public UrlBasedViewResolver setupViewResolver() {
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
}
我使用$routeChangeStart
和http-auth-interceptor
来实现我的应用的登录
ehre是我的javascritp文件
angular.module('SistemaActividades')
.run(function ($rootScope, $location, $http, AuthSharedService, Session,
USER_ROLES, $q, $timeout) {
$rootScope.$on('$routeChangeStart', function (event, next) {
if (next.originalPath === "http://localhost:8080/SpringMVCTemplateAnn/login" && $rootScope.authenticated) {
console.log('entre en el primer if del interceptor');
event.preventDefault();
console.log('registrese');
} else if (next.access && next.access.loginRequired && !$rootScope.authenticated) {
console.log('entre en el segundo if del interceptor')
event.preventDefault();
$rootScope.$broadcast("event:auth-loginRequired", {});
} else if (next.access && !AuthSharedService.isAuthorized(next.access.authorizedRoles)) {
console.log('entre en el tercer if del interceptor')
event.preventDefault();
$rootScope.$broadcast("event:auth-forbidden", {});
}
});
// Call when the the client is confirmed
$rootScope.$on('event:auth-loginConfirmed', function (event, data) {
console.log('login confirmed start ' + data);
alert(data.toSource());
console.log('la URLVALE' + $rootScope.requestedUrl);
$rootScope.loadingAccount = false;
var nextLocation = ($rootScope.requestedUrl ? $rootScope.requestedUrl : "/crearRol");
console.log('la URL2VALE' + $rootScope.requestedUrl);
var delay = ($location.path() === "/loading" ? 1500 : 0);
// console.log('la variable nextlocation vale ' + !!nextlocation);
$timeout(function () {
Session.create(data);
$rootScope.account = Session;
$rootScope.authenticated = true;
$location.path(nextLocation).replace();
}, delay);
});
// Call when the 401 response is returned by the server
$rootScope.$on('event:auth-loginRequired', function (event, data) {
console.log("2do 401 segundo interceptor");
if ($rootScope.loadingAccount && data.status !== 401) {
$rootScope.requestedUrl = $location.path()
$location.path('/loading');
} else {
Session.invalidate();
$rootScope.authenticated = false;
$rootScope.loadingAccount = false;
$location.path('/login');
}
});
// Call when the 403 response is returned by the server
$rootScope.$on('event:auth-forbidden', function (rejection) {
console.log("3 er 403 tercer interceptor");
$rootScope.$evalAsync(function () {
$location.path('/crearPermiso').replace();
});
});
});
这是我的路线javascript文件
angular.module('SistemaActividades')
.config(['$routeProvider', 'USER_ROLES', function ($routeProvider, USER_ROLES) {
$routeProvider.
when('/', {
templateUrl: '/SpringMVCTemplateAnn/resources/angular/templates/dashboardTemplates/dashboardTemplate.html',
controller: 'DashBoardCtrl',
access: {
loginRequired: true,
authorizedRoles: "*"
}
}).
when('/login', {
templateUrl: '/SpringMVCTemplateAnn/resources/angular/templates/loginTemplate/login.html',
controller: 'LoginController',
access: {
loginRequired: false,
authorizedRoles: [USER_ROLES.all]
}
}).
when('/logout', {
templateUrl: '/SpringMVCTemplateAnn/resources/angular/templates/loginTemplate/login.html',
controller: 'LogoutController'
}).
when('/protegida', {
templateUrl: '/SpringMVCTemplateAnn/resources/private/privatePartials/protegida.html',
controller: 'UsuarioCtrl'
}).
});
}]);
angularjs中的我的身份验证服务
angular.module('SistemaActividades')
.service('AuthSharedService', function ($rootScope, $http, authService, Session) {
return {
login: function (userName, password, rememberMe) {
console.log('presione el click');
var config = {
params: {
username: userName,
password: password,
rememberme: rememberMe
},
ignoreAuthModule: 'ignoreAuthModule'
};
$http.post('http://localhost:8080/SpringMVCTemplateAnn/login', '', config)
.success(function (data, status, headers, config) {
authService.loginConfirmed(data);
}).error(function (data, status, headers, config) {
$rootScope.authenticationError = true;
Session.invalidate();
});
},
getAccount: function () {
$rootScope.loadingAccount = true;
$http.get('security/account')
.then(function (response) {
authService.loginConfirmed(response.data);
});
},
isAuthorized: function (authorizedRoles) {
console.log('los roles valen ' + authorizedRoles);
if (!angular.isArray(authorizedRoles)) {
if (authorizedRoles == '*') {
return true;
}
authorizedRoles = [authorizedRoles];
}
var isAuthorized = false;
angular.forEach(authorizedRoles, function (authorizedRole) {
var authorized = (!!Session.login &&
Session.userRoles.indexOf(authorizedRole) !== -1);
if (authorized || authorizedRole == '*') {
isAuthorized = true;
}
});
return isAuthorized;
}
logout: function () {
console.log('entre en el log de logut');
$rootScope.authenticationError = false;
$rootScope.authenticated = false;
$rootScope.account = null;
$http.get('http://localhost:8080/SpringMVCTemplateAnn/logout');
Session.invalidate();
authService.loginCancelled();
}
};
});
我在angularjs中的登录服务
angular.module('SistemaActividades')
.service('Session', function () {
this.create = function (data) {
this.id = data.id;
this.login = data.login;
this.firstName = data.firstName;
this.lastName = data.familyName;
this.email = data.email;
this.userRoles = [];
angular.forEach(data.authorities, function (value, key) {
this.push(value.name);
}, this.userRoles);
};
this.invalidate = function () {
this.id = null;
this.login = null;
this.firstName = null;
this.lastName = null;
this.email = null;
this.userRoles = null;
};
return this;
});
我的登录控制器在angularjs
angular.module('SistemaActividades')
.controller('LoginController', ['$rootScope', '$scope', 'AuthSharedService', function ($rootScope, $scope, AuthSharedService) {
$scope.rememberMe = true;
$scope.login = function () {
console.log('pressione click');
$rootScope.authenticationError = false;
AuthSharedService.login(
$scope.username,
$scope.password,
$scope.rememberMe
);
};
}]);
我的logOut控制器在angularjs
angular.module('SistemaActividades')
.controller('LogoutController', ['$rootScope', '$scope', 'AuthSharedService', function ($rootScope, $scope, AuthSharedService) {
AuthSharedService.logout();
}]);
我的登录页面
<div class="bg-extended">
<div class="align-vertical-center">
<div class="container">
<div class="row">
<div class="well col-sm-offset-3 col-sm-6">
<div class="well-heading well-primary">
<h1>Sign in your account</h1>
</div>
<form class="well-body">
<div class="alert alert-dismissible alert-info">
<button type="button" class="close" data-dismiss="alert">×</button>
<strong>Usuarios de Prueba!</strong> <br/>
<ul>
<li><strong>usuarioNormal / laclave</strong> usuario normal</li>
<li><strong>usuarioAdmin / clave123</strong> admin</li>
</ul>
</div>
<div class="form-group label-floating"
ng-class="{
'has-error is-focused' : authenticationError}">
<label class="control-label" for="login">Login</label>
<input id="login" type="text" class="form-control" ng-model="username"
required="required"/>
<span ng-show="authenticationError" class="help-block">
Please check your credentials and try again.
</span>
</div>
<div class="form-group label-floating">
<label class="control-label" for="password">Password</label>
<input id="password" type="password" class="form-control" ng-model="password"
required="required"/>
</div>
<div class="checkbox">
<label>
<input type="checkbox" ng-model="rememberMe"/><span> Remember me</span>
</label>
</div>
<br/>
<div class="col-sm-offset-3 col-sm-6">
<button class="btn btn-lg btn-primary btn-block" ng-click="login()">
login
</button>
</div>
</form>
</div>
</div>
</div>
</div>
我在java中的登录控制器
@Controller
public class LoginController {
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String login(ModelMap map) {
return "login";
}
@RequestMapping(value = "/logout", method = RequestMethod.GET)
public String logout(ModelMap map, HttpServletRequest request, HttpServletResponse response) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
System.out.println("el usuario vale en logout" + auth.getName().toString());
if (auth != null) {
new SecurityContextLogoutHandler().logout(request, response, auth);
}
return "/login";
}
}
编辑:我设法让spring安全保护我资源中的私人文件夹中的部分,但是在我刷新页面或重新加载页面后我丢失了会话,无论什么角色,我都可以访问私有页面我有,当我刷新页面时,我被重定向到登录页面,如果我使用具有正常角色的用户登录,则该用户可以进入受管理的受保护页面