SSM环境配置好SSM环境以后,配置SpringSecurity环境
security依赖
<dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>4.1.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>4.1.0.RELEASE</version> </dependency>springSecurity配置文件
实现方法,通过application域对象实现,和整合spring和mybatis的方法相同
<listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:springSecurity.xml </param-value> </context-param> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class> org.springframework.web.filter.DelegatingFilterProxy </filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>spring提供的监听器加载security配置文件。3. 书写springSecurity配置文件
<security:http>
<security:intercept-url pattern="add" access="hasAuthority('ROLE_USER')" />
<security:intercept-url pattern="index.jsp" access="permitAll()"/>
<security:intercept-url pattern="/login" access="permitAll()"/>
<security:intercept-url pattern="/*" access="isFullyAuthenticated()"/>
<security:form-login login-page="/login" login-processing-url="/login"
authentication-failure-handler-ref="failureHandler"
authentication-success-handler-ref="successHandler">
</security:form-login>
<security:csrf disabled="true"></security:csrf>
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user
name="username"
password="username"
authorities="ROLE_USER">
</security:user>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
<bean id="successHandler" class="com.bywlstudio.security.SuccessHandler"></bean>
<bean id="failureHandler" class="com.bywlstudio.security.FailureHandler"></bean>security:http配置权限拦截的方式是基于HTTP的security:form-login基于表单(常用)security:http-basic基本的验证方式(不常用)secutity:authentication-manager具体的权限管理配置security:intercept-url配置需要拦截的资源access配置可以访问的权限(取值参考:security官方文档)pattern配置需要拦截的资源(上面的资源使用MVC控制)security:csrf一种浏览器的防护机制,后期文章会详细说明security:authentication-provider具体的实现权限控制security:user配置一个具体的用户authorities配置当前用户所具有的权限,在intercept-url中使用4. 配置成功和失败的处理器
通过实现AuthenticationSuccessHandler接口和AuthenticationFailureHandler实现
public class FailureHandler implements AuthenticationFailureHandler { @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException { response.getWriter().write(WriteStatusJson.loginStatus("status","Failure")); } } public class SuccessHandler implements AuthenticationSuccessHandler { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { response.getWriter().write(WriteStatusJson.loginStatus("status","success")); } }
WriteStatusJson这个类是笔者自定义的一个回状态的工具类,具体实现如下 public class WriteStatusJson {
/**
* 返回登陆状态信息
* @param attritute 登陆的状态
* @param value 登陆的成功过或者失败的返回值
* @param <E> 根据每一次状态返回的值而定
* @return {String} 返回一个json字符串
* @throws JsonProcessingException
*/
public static <E> String loginStatus(String attritute , E value)
throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
Map<String,E> map = new HashMap<>();
map.put(attritute,value);
return objectMapper.writeValueAsString(map);
}
} - 主要功能,将需要返回的状态信息转换为字符串(字符串转换使用了`Jackson`)此时一个基本的权限功能已经结束。
存在的问题:
xml文件。解决问题的思路
Java代码生成一个User并且赋予它一定的权限UserDetailsSevrice重写里面的方法loadUserByUsernameUserDetails类型,Spring提供了一个类User实现了UserDetails查看User类的源码 private static final long serialVersionUID = 410L;//序列化
private String password;//密码
private final String username;//用户名
private final Set<GrantedAuthority> authorities;//权限的集合
private final boolean accountNonExpired;//权限是否过期
private final boolean accountNonLocked;//权限是否被锁定
private final boolean credentialsNonExpired;//凭据未过期
private final boolean enabled;//账户可以使用public class UserAuthent implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
User user = new User("MakerStack","love", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER,ROLE_ADMIN"));
return user;
}
}AuthorityUtils工具类给用户赋予权限,类似于xml中的authorities属性存在的问题
spring自带的User对象来赋值,不能连接数据库解决思路
spring自带的User通过实现了UserDetails接口来实现对用户权限的添加User类实现UserDetails接口,创建操纵User类的持久层接口,获取数据库中的User对象**具体实现
2. 编写数据库表的ORM映射,编写持久层接口,服务层接口
3. 创建实现UserDetailsService接口的类,实现方法
User user = userService.findUserByUsername(username); if(user!=null){ List<Authority> authorities = userService.findAuthorityByUsername(username); //需要对user的List<Authority>集合赋值 List<GrantedAuthority> grantedAuthorities = new ArrayList<>(); for (Authority authority : authorities) { GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(authority.getTag()); grantedAuthorities.add(grantedAuthority); } user.setAuthorities(grantedAuthorities); } return user;
loadUserByUsername方法的参数即为用户在表单中输入的用户名(后期会出一篇security执行流程的文章,可以关注一下)User实现了UserDetails接口,内部定义了一个存储用户权限的集合。现在需要做的就是将数据库中的权限信息添加到这个集合中。spring提供的接口GrantedAuthority来实现;通过其子类SimpleGrantedAuthority将数据库中的权限信息写入,赋值给GrantedAuthority类型,添加到一个集合中,将这个集合赋值给user类的权限集合
数据库整合完成需要注意的问题
name属性必须保证,否则会出现loadUserByUsername方法获取不到参数的问题usernamepasswordsecurity无法读取Access denied for user 'root'@'localhost'(using password: YES)且你之前连接数据库是正确的,则检查你得数据库配置文件目前数据库中存放的密码均为明文传输,所以需要对密码进行加密,而
security提供了为密码加密的算法
步骤
security提供的接口PasswordEncoder的实现类BCryptPasswordEncoder实现用户密码的加密和匹配PasswordEncoder中的方法
String encode(CharSequence var1); boolean matches(CharSequence var1, String var2);BCryptPasswordEncoder类的bean对象