密码加密、基于Shiro实现权限管理
基于Springboot实现新闻搜索、新闻评论、主页最新新闻、关于我页面的显示
源码已上传至Github: 项目源码
一、密码加密
基于MD5密码加密,在本次项目中,手动将加密后的数据存入数据库,然后借助MD5Util工具类进行登录验证
MD5Util.java
package com.wzx.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Util {
/**
* MD5加密类
* @param str 要加密的字符串
* @return 加密后的字符串
*/
public static String code(String str){
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(str.getBytes());
byte[]byteDigest = md.digest();
int i;
StringBuffer buf = new StringBuffer("");
for (int offset = 0; offset < byteDigest.length; offset++) {
i = byteDigest[offset];
if (i < 0)
i += 256;
if (i < 16)
buf.append("0");
buf.append(Integer.toHexString(i));
}
//32位加密
return buf.toString();
// 16位的加密
//return buf.toString().substring(8, 24);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) {
System.out.println(code("123"));
}
}
UserServiceImpl
@Override
public User CheckUser(String username, String password) {
return userDao.findByUsernameAndPassword(username, MD5Util.code(password));
}
二、基于Shiro实现权限管理
Shiro是一个非常强大的、易于使用的、开源的、权限框架。它包括了权限校验、权限授予、会话管理、安全加密等组件。
shiro结构:
- Authentication:权限校验,每次操作校验用户是否有访问权限
- Authorization:授权,用户登录时,授予用户对应的权限
- Session Management:会话管理,用于记录用户的登录状态
- Cryptography:加密,加密算法的实现(SHA、MD5)
- web Support:对Web项目的支持,Shiro的标签
shiro访问过程:
1.首先应用访问(可以使用远程调用,可以是Web请求等),Shiro通过一个Subject对象来标识当前访问的身份。这句话告诉我们,第一次访问的时候,Shiro肯定会创建一个Subject对象标签当前请求(用户)的身份。
2.SecurityManger容器创建一个Subject对象验证请求的参数,SecurityManager的作用是统一管理Subject。这句话意味着,一个SecurityManager对象管理多个Subject的对象。
3.Subject通过SecurityManger获得操作当前用户的权限,在启动的那一刻,SecurityManger就会加载shiro.ini权限配置文件,在用户登录成功后,可以根据shiro配置的信息,获得用户对应的权限。
4.shiro配置:是一个权限控制信息文件,里面必须包括用户的验证信息,权限的信息
在po中新建两个实体类用于权限管理,在User中添加与role的对应关系
Role.java
package com.wzx.po;
import com.fasterxml.jackson.annotation.JsonIgnore;
import javax.persistence.*;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
@Entity
@Table(name = "t_role")
public class Role implements Serializable {
private static final long serialVersionUID = 594829320797158219L;
@Id
private String id;
private String name;
private String description;
//角色与用户 多对多
@ManyToMany(mappedBy="roles")
private Set<User> users = new HashSet<User>(0);
//角色与权限 多对多
@ManyToMany(fetch = FetchType.EAGER)
private Set<Permission> permissions = new HashSet<Permission>(0);
public static long getSerialVersionUID() {
return serialVersionUID;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
public Set<Permission> getPermissions() {
return permissions;
}
public void setPermissions(Set<Permission> permissions) {
this.permissions = permissions;
}
}
package com.wzx.po;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
Permission.java
@Entity
@Table(name = "t_permission")
public class Permission implements Serializable {
private static final long serialVersionUID = -4990810027542971546L;
/**
* 主键
*/
@Id
private String id;
private String name;
private String code;
private String description;
public static long getSerialVersionUID() {
return serialVersionUID;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
//User.java
@ManyToMany(fetch = FetchType.EAGER)
private Set<Role> roles=new HashSet<Role>(0);
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
新建一个realm包用于权限管理,在realm中建立Newsrealm继承AuthorizingRealm,权限管理分为两步认证和授权
认证
//完成认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken token=(UsernamePasswordToken) authenticationToken;
String username = token.getUsername();
String password = new String(token.getPassword());
User user = userService.CheckUser(username, password);
if(user!=null){
return new SimpleAuthenticationInfo(user,password,this.getName());
}
return null;
}
授权
//完成授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
User user = (User)principalCollection.getPrimaryPrincipal();
Set<Role> roles=user.getRoles();
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
for(Role role:roles){
info.addRole(role.getName());
for(Permission p:role.getPermissions()){
info.addStringPermission(p.getCode());
}
}
return info;
}
在LoginController中完成登录
public String login(String username, String password, HttpSession session, RedirectAttributes redirectAttributes){
// User user=userService.CheckUser(username,password);
// if(user!=null){
// session.setAttribute("user",user);
// return "admin/index";
// }else {
// redirectAttributes.addFlashAttribute("message","用户名和密码错误1");
// return "redirect:/admin";
// }
try {
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
Subject subject = SecurityUtils.getSubject();
subject.login(token);
User user=(User)subject.getPrincipal();
session.setAttribute("user",user);
return "admin/index";
}catch (Exception e){
redirectAttributes.addFlashAttribute("message","用户名和密码错误1");
return "redirect:/admin";
}
}
在ShiroConfiguration中配置相关权限信息
package com.wzx;
import com.wzx.realm.NewsRealm;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
@Configuration
public class ShiroConfiguration {
@Bean
public NewsRealm getRealm(){
return new NewsRealm();
}
@Bean
public SecurityManager securityManager(NewsRealm realm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager((realm));
return securityManager;
}
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
shiroFilterFactoryBean.setLoginUrl("/admin");
//shiroFilterFactoryBean.setUnauthorizedUrl("/admin/unauthor");
Map<String,String> filterMap=new LinkedHashMap<>();
filterMap.put("/admin/login","anon");
filterMap.put("/admin/**","authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
return shiroFilterFactoryBean;
}
@Bean
public SimpleMappingExceptionResolver resolver() {
SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();
Properties properties = new Properties();
properties.setProperty("org.apache.shiro.authz.UnauthorizedException", "/error/403");
resolver.setExceptionMappings(properties);
return resolver;
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
AuthorizationAttributeSourceAdvisor advisor=new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
}